Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
},
"dependencies": {
"@hookform/resolvers": "^3.9.1",
"@polinetwork/backend": "^0.12.1",
"@polinetwork/backend": "^0.14.0",
"@radix-ui/react-alert-dialog": "^1.1.3",
"@radix-ui/react-avatar": "^1.1.1",
"@radix-ui/react-collapsible": "^1.1.1",
Expand All @@ -27,19 +27,20 @@
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.4",
"@t3-oss/env-nextjs": "^0.10.1",
"@tanstack/react-query": "^5.90.12",
"@t3-oss/env-nextjs": "^0.13.10",
"@tanstack/react-query": "^5.90.19",
"@tanstack/react-table": "^8.21.2",
"@trpc/client": "11.5.1",
"@trpc/next": "11.5.1",
"@trpc/react-query": "11.5.1",
"@trpc/tanstack-react-query": "11.5.1",
"better-auth": "^1.4.15",
"babel-plugin-react-compiler": "1.0.0",
"better-auth": "^1.3.15",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"geist": "^1.3.0",
"input-otp": "^1.4.2",
"lucide-react": "^0.525.0",
"next": "^15.5.9",
"next-themes": "^0.4.4",
Expand All @@ -53,7 +54,7 @@
"tailwind-merge": "^3.0.1",
"tailwind-scrollbar": "^4.0.2",
"tailwindcss-animate": "^1.0.7",
"zod": "^3.23.3"
"zod": "^4.3.5"
},
"devDependencies": {
"@biomejs/biome": "2.3.10",
Expand Down
461 changes: 176 additions & 285 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

24 changes: 18 additions & 6 deletions src/app/dashboard/(active)/account/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { CircleAlert, UserIcon } from "lucide-react"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { getInitials } from "@/lib/utils"
import { getServerSession } from "@/server/auth"
import { SetName } from "./set-name"
import { Telegram } from "./telegram"

export default async function Account() {
Expand All @@ -16,14 +18,24 @@ export default async function Account() {
<div className="flex gap-4">
<Avatar className="h-32 w-32 rounded-lg">
{user.image && <AvatarImage src={user.image} alt={`propic of ${user.name}`} />}
<AvatarFallback className="rounded-lg">{getInitials(user.name)}</AvatarFallback>
<AvatarFallback className="rounded-lg text-3xl">
{user.name ? getInitials(user.name) : <UserIcon size={48} />}
</AvatarFallback>
</Avatar>

<div>
<p>{user.name}</p>
<p>{user.email}</p>
<div className="mt-2 flex items-center gap-2">
<p className="text-accent-foreground/70">Telegram: </p>
<div className="flex flex-col gap-2">
<div className="flex items-center gap-2">
{!user.name && <CircleAlert className="text-yellow-500" />}
<span className="text-accent-foreground/70">Name:</span>
{user.name ? <p>{user.name}</p> : <SetName />}
</div>

<div className="flex items-center gap-2">
<span className="text-accent-foreground/70">Email:</span>
<p>{user.email}</p>
</div>
<div className="flex items-center gap-2">
<span className="text-accent-foreground/70">Telegram:</span>
<Telegram />
</div>
</div>
Expand Down
66 changes: 66 additions & 0 deletions src/app/dashboard/(active)/account/set-name.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"use client"

import { useRouter } from "next/navigation"
import { type FormEvent, useState } from "react"
import { Button } from "@/components/ui/button"
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { auth } from "@/lib/auth"

export function SetName({ initialName }: { initialName?: string }) {
const router = useRouter()
const [name, setName] = useState<string>(initialName ?? "")
const [open, setOpen] = useState<boolean>(false)

async function handleUpdate(e: FormEvent<HTMLFormElement>) {
e.preventDefault()
await auth.updateUser({ name })
setOpen(false)
router.refresh()
}

return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button variant="outline">Set name</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Set your name</DialogTitle>
<DialogDescription>Make changes to your profile here. Click save when you&apos;re done.</DialogDescription>
</DialogHeader>
<form onSubmit={handleUpdate}>
<div className="grid gap-4">
<div className="grid gap-3">
<Label htmlFor="name">Name</Label>
<Input
id="name"
name="name"
type="text"
autoComplete="name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</div>
</div>
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">Cancel</Button>
</DialogClose>
<Button type="submit">Save changes</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
)
}
2 changes: 1 addition & 1 deletion src/app/dashboard/(active)/account/telegram.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function ShowTelegram({ username, userId }: { username: string; userId: number }
<>
<span>@{username}</span>
{!isLoading && data?.roles?.length && (
<span className="text-foreground/30 text-xs">(roles: {data.roles.join(" ")})</span>
<span className="text-foreground/30 text-xs">(roles: {data.roles.join(", ")})</span>
)}
</>
)
Expand Down
20 changes: 20 additions & 0 deletions src/app/dashboard/(active)/complete-profile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"use client"

import type { User } from "better-auth"
import { UserRoundPenIcon } from "lucide-react"
import Link from "next/link"
import { Button } from "@/components/ui/button"

export function CompleteProfile({ user }: { user: User }) {
return (
!user.name && (
<div className="flex items-center p-2 pl-4 mb-4 gap-2 rounded-lg border text-accent-foreground bg-yellow-400/10 border-yellow-400">
<UserRoundPenIcon size={16} />
<p className="grow">Your profile is incomplete, please enter the missing information.</p>
<Link href="/dashboard/account">
<Button>Go complete</Button>
</Link>
</div>
)
)
}
4 changes: 3 additions & 1 deletion src/app/dashboard/(active)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { getServerSession } from "@/server/auth"
import { CompleteProfile } from "./complete-profile"

export default async function AdminHome() {
const session = await getServerSession()
const { data: session } = await getServerSession()
return (
session && (
<div className="container mx-auto px-4 py-8">
<CompleteProfile user={session.user} />
<h2 className="text-accent-foreground mb-4 text-3xl font-bold">Home</h2>
</div>
)
Expand Down
19 changes: 12 additions & 7 deletions src/app/dashboard/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import { redirect } from "next/navigation"
import { Header } from "@/components/header"
import { SidebarProvider } from "@/components/ui/sidebar"
import { getQueryClient, trpc } from "@/lib/trpc/server"
import { getServerSession } from "@/server/auth"

export default async function AdminLayout({ children }: { children: React.ReactNode }) {
const session = await getServerSession()
// console.log(session)
if (!session.data) redirect("/login")

return (
<div className="flex h-screen w-full flex-col items-center justify-start overflow-y-hidden">
<Header />
<SidebarProvider>{children}</SidebarProvider>
</div>
)
const tgId = session.data.user.telegramId
if (!tgId) redirect("/onboarding/link")
// if (session?.user.role === USER_ROLE.INACTIVE) ;
// if (session?.user.role === USER_ROLE.DISABLED) redirect("/dashboard/disabled");

const qc = getQueryClient()
const { roles } = await qc.fetchQuery(trpc.tg.permissions.getRoles.queryOptions({ userId: tgId }))
if (!roles || roles.length === 0) redirect("/onboarding/no-role")
if (roles.includes("creator")) redirect("/onboarding/unauthorized")

return <SidebarProvider>{children}</SidebarProvider>
}
11 changes: 8 additions & 3 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { GeistSans } from "geist/font/sans"
import type { Metadata } from "next"
import "@/index.css"
import { HEADER_HEIGHT } from "@/components/header"
import { HEADER_HEIGHT, Header } from "@/components/header"
import { ThemeProvider } from "@/components/theme-provider"
import { Toaster } from "@/components/ui/sonner"
import { TooltipProvider } from "@/components/ui/tooltip"
Expand Down Expand Up @@ -37,8 +37,13 @@ export default function RootLayout({ children }: Readonly<{ children: React.Reac
disableTransitionOnChange
>
<TooltipProvider>
<TRPCReactProvider>{children}</TRPCReactProvider>
<Toaster richColors position="bottom-right" />
<TRPCReactProvider>
<div className="flex h-screen w-full flex-col items-center justify-start">
<Header />
{children}
</div>
</TRPCReactProvider>
<Toaster richColors position="bottom-center" />
</TooltipProvider>
</ThemeProvider>
</body>
Expand Down
6 changes: 3 additions & 3 deletions src/app/login/can-i-access.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export function CanIAccess() {
className="place-self-center justify-self-center"
/>
<div className="text-center">
<p className="text-primary text-xl font-bold dark:text-white">1. Login with GitHub</p>
<p className="text-muted-foreground text-xs">(provider might change)</p>
<p className="text-primary text-xl font-bold dark:text-white">1. Login with email</p>
<p className="text-muted-foreground text-sm">We send an OTP to your email</p>
</div>
</div>
</Card>
Expand All @@ -49,7 +49,7 @@ export function CanIAccess() {
className="place-self-center justify-self-center"
/>
<div className="text-center">
<p className="text-primary text-lg font-bold dark:text-white">2. Link your Telegram account</p>
<p className="text-primary text-xl font-bold dark:text-white">2. Link your Telegram account</p>
<p className="text-muted-foreground text-sm">This allows to verify your role</p>
</div>
</div>
Expand Down
10 changes: 0 additions & 10 deletions src/app/login/layout.tsx

This file was deleted.

26 changes: 4 additions & 22 deletions src/app/login/github.tsx → src/app/login/login-button.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,18 @@
"use client"
import { LogInIcon } from "lucide-react"
import Image from "next/image"
import Link from "next/link"
import { Card, CardContent } from "@/components/ui/card"
import { signIn } from "@/lib/auth"

export function Github({ callbackURL }: { callbackURL: string }) {
export function LoginButton() {
return (
<button
type="button"
className="h-20 min-h-20 w-full"
onClick={async () => {
await signIn.social({
provider: "github",
callbackURL,
})
}}
>
<Link href="/login" className="h-20 min-h-20 w-full">
<Card className="border-primary from-primary to-primary/20 group relative h-full w-full cursor-pointer overflow-hidden bg-linear-to-r to-60%">
<div className="bg-primary absolute inset-0 opacity-0 transition duration-250 group-hover:opacity-100"></div>
<CardContent className="text-primary-foreground absolute inset-0 flex items-center space-x-4 py-4">
<LogInIcon size={32} />
<p className="flex-1 text-start text-xl">Enter your reserved area</p>
<Image
className="justify-self-end dark:invert-100"
src={`https://authjs.dev/img/providers/github.svg`}
unoptimized
alt={`logo of github`}
width={28}
height={28}
/>
</CardContent>
</Card>
</button>
</Link>
)
}
Loading
Loading