Skip to content

Commit 8585a76

Browse files
committed
feat: profile ui and other small ui sections
1 parent 638d85b commit 8585a76

35 files changed

Lines changed: 2198 additions & 823 deletions

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@
3131
"@radix-ui/react-collapsible": "^1.1.11",
3232
"@radix-ui/react-dialog": "^1.1.14",
3333
"@radix-ui/react-dropdown-menu": "^2.1.15",
34+
"@radix-ui/react-label": "^2.1.7",
3435
"@radix-ui/react-select": "^2.2.5",
3536
"@radix-ui/react-separator": "^1.1.7",
3637
"@radix-ui/react-slot": "^1.2.3",
38+
"@radix-ui/react-switch": "^1.2.5",
39+
"@radix-ui/react-tabs": "^1.1.12",
3740
"@radix-ui/react-tooltip": "^1.2.7",
3841
"@t3-oss/env-nextjs": "^0.12.0",
3942
"@tanstack/react-query": "^5.69.0",
@@ -49,6 +52,7 @@
4952
"lucide-react": "^0.514.0",
5053
"next": "^15.2.3",
5154
"next-auth": "5.0.0-beta.25",
55+
"next-themes": "^0.4.6",
5256
"openai": "^5.1.1",
5357
"react": "^19.0.0",
5458
"react-dom": "^19.0.0",
Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,10 @@
11
"use client";
2-
import Chat from "@/app/_components/Chat"
3-
import { SidebarInset, SidebarProvider, SidebarTrigger, useSidebar } from "@/components/ui/sidebar"
4-
import { UIStructure } from "@/components/ui/ui-structure"
2+
import Chat from "@/app/_components/Chat";
53

64
export default function SingleChatPage() {
7-
const { open } = useSidebar();
8-
return (
9-
<>
10-
<UIStructure />
11-
<SidebarInset className="border-2 p-2 max-h-svh overflow-hidden rounded-xl bg-accent/40">
12-
<SidebarTrigger className={open ? "hidden" : "flex"} />
13-
{/* <nav
14-
className="flex items-center bg-gradient-to-b from-accent/20 h-[50px] px-2 rounded-t-2xl justify-between">
15-
<SidebarTrigger />
16-
<div>Title</div>
17-
18-
</nav> */}
19-
{/* <div className="h-[calc(100%-50px)]"> */}
20-
<Chat />
21-
{/* </div> */}
22-
</SidebarInset>
23-
24-
</>
25-
)
26-
}
5+
return (
6+
<>
7+
<Chat />
8+
</>
9+
);
10+
}

src/app/(app)/ask/layout.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { SidebarToggle } from "@/app/_components/sidebar-toggle";
2+
import {
3+
SidebarInset,
4+
SidebarTrigger,
5+
useSidebar,
6+
} from "@/components/ui/sidebar";
7+
import { SelectTheme } from "@/components/ui/theme-toggler";
8+
import { UIStructure } from "@/components/ui/ui-structure";
9+
import { SlidersHorizontalIcon } from "@phosphor-icons/react/dist/ssr";
10+
import Link from "next/link";
11+
12+
export default function ChatLayout({
13+
children,
14+
}: {
15+
children: React.ReactNode;
16+
}) {
17+
return (
18+
<>
19+
<UIStructure />
20+
<SidebarInset className="!h-svh p-2">
21+
<div className="bg-muted/80 relative h-full max-h-svh w-full overflow-hidden rounded-xl p-4">
22+
<div className="absolute top-0 left-0 flex h-12 w-full items-center justify-between px-3">
23+
<SidebarToggle />
24+
<div className="flex items-center gap-2">
25+
<Link
26+
className="hover:bg-accent flex size-7 items-center justify-center rounded-lg"
27+
href="/settings/subscription"
28+
>
29+
<SlidersHorizontalIcon weight="bold" className="size-5" />
30+
</Link>
31+
<SelectTheme />
32+
</div>
33+
</div>
34+
<div className="mx-auto flex h-full w-full max-w-3xl flex-col">
35+
{children}
36+
</div>
37+
</div>
38+
</SidebarInset>
39+
</>
40+
);
41+
}

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
import React from 'react'
2-
import Chat from '../../_components/Chat'
3-
import { HydrateClient } from '@/trpc/server'
4-
import UIInput from '@/components/ui/ui-input'
1+
import React from "react";
2+
import { HydrateClient } from "@/trpc/server";
3+
import UIInput from "@/components/ui/ui-input";
54

65
const page = () => {
76
return (
87
<HydrateClient>
9-
<div className='flex flex-col max-w-screen min-h-screen justify-center items-center'>
8+
<div className="flex w-full max-w-screen flex-col items-center justify-center">
109
<UIInput />
1110
</div>
1211
</HydrateClient>
13-
)
14-
}
12+
);
13+
};
1514

16-
export default page
15+
export default page;

src/app/(app)/settings/subscription/page.tsx

Lines changed: 123 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -1,147 +1,135 @@
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-
];
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+
import Link from "next/link";
8+
import { ArrowLeftIcon } from "@phosphor-icons/react/dist/ssr";
9+
import SignOut from "@/components/ui/signout";
10+
import { SelectTheme } from "@/components/ui/theme-toggler";
11+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
12+
import { Account } from "@/components/subscription/account";
13+
import { Customisation } from "@/components/subscription/customisation";
14+
import { Profile } from "@/components/subscription/profile/profile";
15+
import Models from "@/components/subscription/model";
16+
import APIKeysPage from "@/components/subscription/api-key";
17+
import { AttachmentsPage } from "@/components/subscription/attachments";
18+
import { ContactUsPage } from "@/components/subscription/contact-us";
19+
import { History } from "@/components/subscription/history";
4720

4821
export default async function SubscriptionPage() {
49-
const user = await FetchUser()
50-
console.log(user)
22+
const user = await FetchUser();
23+
console.log(user);
5124
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-
/>
25+
<div className="bg-background text-foreground min-h-screen w-full border">
26+
<div className="mx-auto w-full max-w-6xl p-8">
27+
<div>
28+
<div className="mb-6 flex items-center justify-between text-2xl font-bold">
29+
<Button asChild variant="ghost" className="font-semibold">
30+
<Link className="flex items-center gap-2" href="/">
31+
<ArrowLeftIcon className="size-4" />
32+
Back to chat
33+
</Link>
34+
</Button>
35+
<div className="flex items-center gap-3">
36+
<SelectTheme />
37+
<SignOut />
38+
</div>
39+
</div>
40+
</div>
41+
<div className="grid grid-cols-1 gap-14 lg:grid-cols-3">
42+
{/* Left Column - Profile and Shortcuts */}
43+
<div className="hidden space-y-8 lg:col-span-1 lg:block">
44+
{/* Profile Section */}
45+
<Profile image={user?.image as string} />
46+
47+
{/* Message Usage */}
48+
<div className="bg-accent space-y-4 rounded-xl p-4 dark:bg-black">
49+
<div className="flex items-center justify-between">
50+
<span className="text-foreground font-medium">
51+
Message Usage
52+
</span>
53+
<span className="text-muted-foreground text-sm">
54+
Resets today at 5:30 AM
55+
</span>
6856
</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>
57+
58+
<div className="space-y-2">
59+
<div className="flex items-center justify-between">
60+
<span className="text-foreground">Standard</span>
61+
<span className="text-foreground font-mono">0/20</span>
8262
</div>
83-
<div className="w-full h-2 bg-muted rounded-full overflow-hidden">
84-
<div className="h-full bg-primary" style={{ width: '0%' }} />
63+
<div className="bg-muted h-2 w-full rounded-full">
64+
<div
65+
className="bg-primary h-2 rounded-full"
66+
style={{ width: "0%" }}
67+
></div>
8568
</div>
86-
<div className="text-xs text-muted-foreground mt-1">20 messages remaining</div>
69+
<p className="text-muted-foreground text-sm">
70+
20 messages remaining
71+
</p>
8772
</div>
88-
</CardContent>
89-
</Card>
73+
</div>
74+
</div>
9075

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>
76+
{/* Right Column - Tabs Section */}
77+
<div className="lg:col-span-2">
78+
<Tabs defaultValue="account" className="max-w-full overflow-x-auto">
79+
<div className="no-scrollbar overflow-x-auto">
80+
<TabsList className="h-[34px] rounded-lg">
81+
<TabsTrigger className="rounded-md text-xs" value="account">
82+
Account
83+
</TabsTrigger>
84+
<TabsTrigger
85+
className="rounded-lg text-xs"
86+
value="customisation"
87+
>
88+
Customisation
89+
</TabsTrigger>
90+
<TabsTrigger className="rounded-lg text-xs" value="history">
91+
History & Sync
92+
</TabsTrigger>
93+
<TabsTrigger className="rounded-lg text-xs" value="models">
94+
Models
95+
</TabsTrigger>
96+
<TabsTrigger className="rounded-lg text-xs" value="api-keys">
97+
API Keys
98+
</TabsTrigger>
99+
<TabsTrigger
100+
className="rounded-lg text-xs"
101+
value="attachments"
102+
>
103+
Attachments
104+
</TabsTrigger>
105+
<TabsTrigger className="rounded-lg text-xs" value="contact">
106+
Contact
107+
</TabsTrigger>
108+
</TabsList>
127109
</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>
110+
<TabsContent value="account" className="mt-6">
111+
<Account />
112+
</TabsContent>
113+
<TabsContent value="customisation">
114+
<Customisation />
115+
</TabsContent>
116+
<TabsContent value="history">
117+
<History />
118+
</TabsContent>
119+
<TabsContent value="models">
120+
<Models />
121+
</TabsContent>
122+
<TabsContent value="api-keys">
123+
<APIKeysPage />
124+
</TabsContent>
125+
<TabsContent value="attachments">
126+
<AttachmentsPage />
127+
</TabsContent>
128+
<TabsContent value="contact">
129+
<ContactUsPage />
130+
</TabsContent>
131+
</Tabs>
132+
</div>
145133
</div>
146134
</div>
147135
</div>

0 commit comments

Comments
 (0)