Skip to content

Commit 638d85b

Browse files
committed
feat: settins
1 parent be16bb9 commit 638d85b

16 files changed

Lines changed: 349 additions & 129 deletions

File tree

next.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import "./src/env.js";
77
/** @type {import("next").NextConfig} */
88
const config = {
99
output: "standalone",
10+
images: {
11+
domains: ["lh3.googleusercontent.com"]
12+
}
1013
};
1114

1215
export default config;

src/actions/fetchUser.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"use server"
2+
import { auth } from "@/server/auth"
3+
import { db } from "@/server/db"
4+
export async function FetchUser() {
5+
const session = await auth()
6+
if (!session) {
7+
return null
8+
}
9+
const user = await db.user.findUnique({
10+
where: { id: session.user.id }
11+
})
12+
13+
return user
14+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import React from 'react'
2-
import Chat from '../_components/Chat'
2+
import Chat from '../../_components/Chat'
33
import { HydrateClient } from '@/trpc/server'
44
import UIInput from '@/components/ui/ui-input'
55

66
const page = () => {
77
return (
88
<HydrateClient>
9-
<div className='flex flex-col w-full max-h-svh gap-4'>
9+
<div className='flex flex-col max-w-screen min-h-screen justify-center items-center'>
1010
<UIInput />
1111
</div>
1212
</HydrateClient>
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import type { ReactNode } from 'react';
2+
import Image from 'next/image';
3+
import { Badge } from '@/components/ui/badge';
4+
import { Button } from '@/components/ui/button';
5+
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
6+
import { FetchUser } from '@/actions/fetchUser';
7+
8+
interface FeatureCardProps {
9+
icon: ReactNode;
10+
title: string;
11+
description: string;
12+
}
13+
14+
function FeatureCard({ icon, title, description }: FeatureCardProps) {
15+
return (
16+
<div className="flex flex-col items-center gap-2 bg-muted/40 rounded-lg p-4 w-full md:w-64">
17+
<div className="text-2xl">{icon}</div>
18+
<div className="font-semibold text-center">{title}</div>
19+
<div className="text-sm text-muted-foreground text-center">{description}</div>
20+
</div>
21+
);
22+
}
23+
24+
const features = [
25+
{
26+
icon: <span role="img" aria-label="rocket">🚀</span>,
27+
title: 'Access to All Models',
28+
description: 'Get access to our full suite of models including Claude, o3-mini-high, and more!'
29+
},
30+
{
31+
icon: <span role="img" aria-label="gift">🎁</span>,
32+
title: 'Generous Limits',
33+
description: 'Receive 1500 standard credits per month, plus 100 premium credits* per month.'
34+
},
35+
{
36+
icon: <span role="img" aria-label="support">🛟</span>,
37+
title: 'Priority Support',
38+
description: 'Get faster responses and dedicated assistance from the T3 team whenever you need help!'
39+
}
40+
];
41+
42+
const keyboardShortcuts = [
43+
{ label: 'Search', keys: ['⌘', 'K'] },
44+
{ label: 'New Chat', keys: ['⌘', 'Shift', 'O'] },
45+
{ label: 'Toggle Sidebar', keys: ['⌘', 'B'] },
46+
];
47+
48+
export default async function SubscriptionPage() {
49+
const user = await FetchUser()
50+
console.log(user)
51+
return (
52+
<div className="min-h-screen bg-background text-foreground flex flex-col items-center py-8 px-2 md:px-0">
53+
<div className="w-full max-w-5xl flex flex-col md:flex-row gap-8">
54+
{/* Left Column */}
55+
<div className="flex-1 flex flex-col gap-6 max-w-md mx-auto md:mx-0">
56+
{/* Profile Card */}
57+
<Card className="bg-muted/40">
58+
<CardHeader className="flex flex-col items-center gap-2 pb-2">
59+
<div className="w-24 h-24 rounded-full overflow-hidden border-4 border-muted">
60+
<Image
61+
src={user?.image || ""}
62+
alt="Profile"
63+
width={96}
64+
height={96}
65+
className="object-cover w-full h-full"
66+
priority
67+
/>
68+
</div>
69+
<CardTitle className="text-xl mt-2">{user?.name}</CardTitle>
70+
<div className="text-muted-foreground text-sm">{user?.email}</div>
71+
<Badge variant="secondary" className="mt-1">Free Plan</Badge>
72+
</CardHeader>
73+
<CardContent>
74+
<div className="bg-background rounded-lg p-4 flex flex-col gap-2 mt-2">
75+
<div className="flex items-center justify-between text-sm">
76+
<span className="text-muted-foreground">Message Usage</span>
77+
<span className="text-muted-foreground">Resets tomorrow at 5:30 AM</span>
78+
</div>
79+
<div className="flex items-center justify-between text-sm">
80+
<span>Standard</span>
81+
<span>0/20</span>
82+
</div>
83+
<div className="w-full h-2 bg-muted rounded-full overflow-hidden">
84+
<div className="h-full bg-primary" style={{ width: '0%' }} />
85+
</div>
86+
<div className="text-xs text-muted-foreground mt-1">20 messages remaining</div>
87+
</div>
88+
</CardContent>
89+
</Card>
90+
91+
{/* Keyboard Shortcuts */}
92+
<Card className="bg-muted/40">
93+
<CardHeader>
94+
<CardTitle className="text-base">Keyboard Shortcuts</CardTitle>
95+
</CardHeader>
96+
<CardContent className="flex flex-col gap-3">
97+
{keyboardShortcuts.map(shortcut => (
98+
<div key={shortcut.label} className="flex items-center justify-between">
99+
<span>{shortcut.label}</span>
100+
<span className="flex gap-1">
101+
{shortcut.keys.map(key => (
102+
<kbd key={key} className="bg-muted px-2 py-1 rounded text-xs font-mono border border-border">{key}</kbd>
103+
))}
104+
</span>
105+
</div>
106+
))}
107+
</CardContent>
108+
</Card>
109+
</div>
110+
111+
{/* Right Column */}
112+
<div className="flex-1 flex flex-col gap-6">
113+
{/* Upgrade to Pro */}
114+
<Card className="bg-muted/40">
115+
<CardHeader>
116+
<CardTitle className="text-xl">Upgrade to Pro</CardTitle>
117+
</CardHeader>
118+
<CardContent>
119+
<div className="flex flex-col md:flex-row gap-4 mb-6">
120+
{features.map(f => (
121+
<FeatureCard key={f.title} {...f} />
122+
))}
123+
</div>
124+
<div className="flex items-center gap-4 mb-2">
125+
<span className="text-2xl font-bold">$8</span>
126+
<span className="text-muted-foreground">/month</span>
127+
</div>
128+
<Button className="bg-pink-600 hover:bg-pink-700 text-white w-full max-w-xs">Upgrade Now</Button>
129+
<div className="text-xs text-muted-foreground mt-2">
130+
* Premium credits are used for GPT Image Gen, Claude Sonnet, and Grok 3. Additional Premium credits can be purchased separately.
131+
</div>
132+
</CardContent>
133+
</Card>
134+
135+
{/* Danger Zone */}
136+
<Card className="bg-muted/40">
137+
<CardHeader>
138+
<CardTitle className="text-lg text-destructive">Danger Zone</CardTitle>
139+
</CardHeader>
140+
<CardContent>
141+
<div className="mb-2 text-sm">Permanently delete your account and all associated data.</div>
142+
<Button variant="destructive" className="w-full max-w-xs">Delete Account</Button>
143+
</CardContent>
144+
</Card>
145+
</div>
146+
</div>
147+
</div>
148+
);
149+
}

src/app/(auth)/auth/page.tsx

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
"use client"
2+
import { useRouter } from "next/navigation";
3+
import { signIn } from "next-auth/react";
4+
import { ArrowLeft } from "lucide-react";
5+
import { Button } from "@/components/ui/button";
6+
7+
function LoginPage() {
8+
const router = useRouter();
9+
10+
return (
11+
<div className="min-h-screen bg-[#1B1519] flex flex-col">
12+
{/* Back to Chat Button */}
13+
<div className="absolute top-6 left-6">
14+
<Button
15+
type="button"
16+
variant="ghost"
17+
className="flex items-center gap-2 text-gray-300 hover:text-white transition-colors duration-200 px-2 py-1"
18+
aria-label="Back to Chat"
19+
onClick={() => router.back()}
20+
>
21+
<ArrowLeft size={20} />
22+
<span className="text-sm font-medium">Back to Chat</span>
23+
</Button>
24+
</div>
25+
26+
{/* Main Content */}
27+
<main className="flex-1 flex items-center justify-center px-4">
28+
<section className="w-full max-w-md text-center" aria-label="Login">
29+
{/* Welcome Header */}
30+
<header className="mb-8">
31+
<h1 className="text-3xl font-bold text-white mb-4">
32+
Welcome to{" "}
33+
<span className="bg-[#E2BAD1] bg-clip-text text-transparent">
34+
T3.chat
35+
</span>
36+
</h1>
37+
<p className="text-gray-300 text-lg">
38+
Sign in below (we'll increase your message limits if you do 😊)
39+
</p>
40+
</header>
41+
42+
{/* Google Sign In Button */}
43+
<div className="mb-8">
44+
<Button
45+
type="button"
46+
onClick={() => signIn("google")}
47+
className="w-full bg-[#3F1426] hover:bg-[#3F1426]/80 p-8 text-white font-medium py-3 px-6 rounded-lg transition-all duration-200 flex items-center justify-center gap-3 shadow-lg hover:shadow-xl"
48+
aria-label="Continue with Google"
49+
>
50+
<svg className="w-5 h-5" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
51+
<path
52+
fill="currentColor"
53+
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
54+
/>
55+
<path
56+
fill="currentColor"
57+
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
58+
/>
59+
<path
60+
fill="currentColor"
61+
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
62+
/>
63+
<path
64+
fill="currentColor"
65+
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
66+
/>
67+
</svg>
68+
Continue with Google
69+
</Button>
70+
</div>
71+
72+
{/* Terms and Privacy */}
73+
<footer className="text-sm text-gray-400">
74+
By continuing, you agree to our{" "}
75+
<a
76+
href="#"
77+
className="text-gray-300 hover:text-white underline transition-colors duration-200"
78+
>
79+
Terms of Service
80+
</a>{" "}
81+
and{" "}
82+
<a
83+
href="#"
84+
className="text-gray-300 hover:text-white underline transition-colors duration-200"
85+
>
86+
Privacy Policy
87+
</a>
88+
</footer>
89+
</section>
90+
</main>
91+
</div>
92+
);
93+
}
94+
95+
export default LoginPage;

src/app/_components/Chat.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
"use client"
22

33
import React, { useEffect, useState } from 'react'
4-
import axios from 'axios'
54
import { useSession } from "next-auth/react"
65
import { Textarea } from '@/components/ui/textarea'
76
import { Button } from '@/components/ui/button'
87
import { Badge } from '@/components/ui/badge'
9-
import { ChatCircleDotsIcon, MicrophoneIcon, RobotIcon, SpinnerGapIcon } from '@phosphor-icons/react'
8+
import { ChatCircleDotsIcon, MicrophoneIcon } from '@phosphor-icons/react'
109
import remarkGfm from "remark-gfm";
1110
import { useChat } from "@ai-sdk/react";
1211
import ReactMarkdown from "react-markdown";
@@ -25,7 +24,6 @@ const geistMono = Geist_Mono({
2524

2625
const Chat = () => {
2726
const session = useSession()
28-
const [response, setResponse] = useState<string>("")
2927

3028
const { messages, setMessages, input, handleInputChange, handleSubmit, status } =
3129
useChat({

src/app/_components/Feedback.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export const Feedback = () => {
3939
return (
4040
<>
4141
<Toaster />
42-
<div className="min-h-screen bg-gradient-to-b from-gray-900 to-black py-12 px-4 sm:px-6 lg:px-8">
42+
<div className="min-h-screen bg-black py-12 px-4 sm:px-6 lg:px-8">
4343
<div className="max-w-md mx-auto space-y-8">
4444
<div className="text-center">
4545
<h1 className="text-4xl font-extrabold text-white tracking-tight">

src/app/api/ask/route.ts

Lines changed: 0 additions & 39 deletions
This file was deleted.

0 commit comments

Comments
 (0)