Skip to content

Commit 5f4710a

Browse files
feat: remove react-query in favor of server actions (#22)
* checkpoint: user-list user-details (no cards) * checkpoint * checkpoint * checkpoint: user-details components * checkpoint: grants * checkpoint: azure * fix: button as render * checkpoint: account * checkpoint: more grants * fix: typos * checkpoint: groups * checkpoint: group row hide toggle * feat: remove react-query * fix: remove exposure of tRPC * feat: add count for groups and users lists * review * fix: avoid double query in groups * feat: put role check in actions * fix: pending states * fix: update auditlog query * fix: better data fetching * fix: old update state
1 parent 3f8cc16 commit 5f4710a

46 files changed

Lines changed: 640 additions & 677 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,12 @@
1616
"@base-ui/react": "^1.3.0",
1717
"@better-auth/passkey": "^1.5.5",
1818
"@hookform/resolvers": "^3.9.1",
19-
"@polinetwork/backend": "^0.15.15",
19+
"@polinetwork/backend": "^0.15.16",
2020
"@radix-ui/react-dialog": "^1.1.15",
2121
"@t3-oss/env-nextjs": "^0.13.10",
22-
"@tanstack/react-query": "^5.90.19",
2322
"@tanstack/react-table": "^8.21.2",
2423
"@trpc/client": "11.5.1",
2524
"@trpc/next": "11.5.1",
26-
"@trpc/react-query": "11.5.1",
27-
"@trpc/tanstack-react-query": "11.5.1",
2825
"babel-plugin-react-compiler": "1.0.0",
2926
"better-auth": "^1.5.5",
3027
"class-variance-authority": "^0.7.1",

pnpm-lock.yaml

Lines changed: 9 additions & 34 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/(auth)/onboarding/no-role/page.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Image from "next/image"
22
import { redirect } from "next/navigation"
33
import loginSvg2 from "@/assets/svg/login-2.svg"
44
import { Card } from "@/components/ui/card"
5-
import { getQueryClient, trpc } from "@/lib/trpc/server"
5+
import { getUserRoles } from "@/server/actions/users"
66
import { getServerSession } from "@/server/auth"
77
import { Logout } from "../link/logout"
88

@@ -11,8 +11,7 @@ export default async function OnboardingNoRole() {
1111
if (!session) redirect("/login")
1212
if (!session.user.telegramId) redirect("/onboarding/link")
1313

14-
const qc = getQueryClient()
15-
const { roles } = await qc.fetchQuery(trpc.tg.permissions.getRoles.queryOptions({ userId: session.user.telegramId }))
14+
const { roles } = await getUserRoles(session.user.telegramId)
1615
if (roles?.includes("creator")) redirect("/onboarding/unauthorized")
1716
if (roles && roles.length > 0) redirect("/dashboard")
1817

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,17 @@
1-
"use client"
2-
import { useQuery } from "@tanstack/react-query"
3-
import { useSession } from "@/lib/auth"
4-
import { useTRPC } from "@/lib/trpc/client"
1+
import { getUserRoles } from "@/server/actions/users"
2+
import { getServerSession } from "@/server/auth"
53

6-
export function Telegram() {
7-
const { data: session, isPending } = useSession()
8-
if (isPending || !session) return null
4+
export async function Telegram() {
5+
const { data } = await getServerSession()
6+
if (!data || !data.user.telegramId) return null
97

10-
const { user } = session
11-
if (!user.telegramUsername || !user.telegramId) return null
8+
const { roles } = await getUserRoles(data.user.telegramId)
9+
const length = roles?.length ?? 0
1210

13-
return <ShowTelegram username={user.telegramUsername} userId={user.telegramId} />
14-
}
15-
16-
function ShowTelegram({ username, userId }: { username: string; userId: number }) {
17-
const trpc = useTRPC()
18-
const { data, isLoading } = useQuery(trpc.tg.permissions.getRoles.queryOptions({ userId }))
1911
return (
2012
<>
21-
<span>@{username}</span>
22-
{!isLoading && data?.roles?.length && (
23-
<span className="text-foreground/30 text-xs">(roles: {data.roles.join(", ")})</span>
24-
)}
13+
<span>{data.user.telegramUsername ? `@${data.user.telegramUsername}` : data.user.id}</span>
14+
{roles && length > 0 && <span className="text-foreground/30 text-xs">(roles: {roles.join(", ")})</span>}
2515
</>
2616
)
2717
}

src/app/dashboard/(active)/azure/members/columns.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
"use client"
22
import { createColumnHelper, type Row } from "@tanstack/react-table"
33
import { Badge } from "@/components/ui/badge"
4-
import type { ApiOutput } from "@/lib/trpc/types"
5-
import { SetAssocNumberDialog } from "./_components/set-assoc-number-dialog"
4+
import type { AzureMember } from "@/server/trpc/types"
5+
import { SetAssocNumberDialog } from "./set-assoc-number-dialog"
66

7-
type ParsedUser = ApiOutput["azure"]["members"]["getAll"][0]
8-
const ch = createColumnHelper<ParsedUser>()
7+
const ch = createColumnHelper<AzureMember>()
98

109
export const columns = [
1110
ch.accessor("employeeId", {
@@ -46,6 +45,6 @@ export const columns = [
4645
}),
4746
]
4847

49-
function RowActions({ row: _ }: { row: Row<ParsedUser> }) {
48+
function RowActions({ row: _ }: { row: Row<AzureMember> }) {
5049
return <div className="flex gap-2 justify-start items-center"></div>
5150
}

src/components/create-assoc-member.tsx renamed to src/app/dashboard/(active)/azure/members/create-assoc-member.tsx

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
"use client"
2-
import { useMutation } from "@tanstack/react-query"
32
import { useRouter } from "next/navigation"
4-
import { useState } from "react"
3+
import { useState, useTransition } from "react"
54
import { toast } from "sonner"
5+
import { Button } from "@/components/ui/button"
6+
import { Input } from "@/components/ui/input"
7+
import { Label } from "@/components/ui/label"
68
import {
79
Sheet,
810
SheetClose,
@@ -12,22 +14,16 @@ import {
1214
SheetTitle,
1315
SheetTrigger,
1416
} from "@/components/ui/sheet"
15-
import { useTRPC } from "@/lib/trpc/client"
16-
import { Button } from "./ui/button"
17-
import { Input } from "./ui/input"
18-
import { Label } from "./ui/label"
17+
import { createAzureMember } from "@/server/actions/azure"
1918

2019
export function CreateAssocUser() {
2120
const [open, setOpen] = useState<boolean>(false)
2221
const [firstName, setFirstName] = useState<string>("")
2322
const [lastName, setLastName] = useState<string>("")
2423
const [assocNumber, setAssocNumber] = useState<string>("")
2524
const [sendTo, setSendTo] = useState<string>("")
26-
const trpc = useTRPC()
2725
const router = useRouter()
2826

29-
const { mutateAsync, isPending } = useMutation(trpc.azure.members.create.mutationOptions())
30-
3127
function handleOpenChange(v: boolean): void {
3228
setOpen(v)
3329
setFirstName("")
@@ -36,11 +32,23 @@ export function CreateAssocUser() {
3632
setSendTo("")
3733
}
3834

39-
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
40-
e.preventDefault()
35+
const [pending, startTransition] = useTransition()
36+
37+
async function handleSubmit() {
4138
if (!assocNumber || Number.isNaN(parseInt(assocNumber, 10))) return
4239

43-
const res = await mutateAsync({ assocNumber: parseInt(assocNumber, 10), firstName, lastName, sendEmailTo: sendTo })
40+
const res = await createAzureMember({
41+
assocNumber: parseInt(assocNumber, 10),
42+
firstName,
43+
lastName,
44+
sendEmailTo: sendTo,
45+
}).catch(() => null)
46+
47+
if (!res) {
48+
toast.error("There was an error")
49+
return
50+
}
51+
4452
if (res.error !== null) {
4553
toast.error(res.error)
4654
return
@@ -59,7 +67,7 @@ export function CreateAssocUser() {
5967
<SheetHeader className="px-0">
6068
<SheetTitle>Create new member account</SheetTitle>
6169
</SheetHeader>
62-
<form onSubmit={handleSubmit}>
70+
<form action={() => startTransition(handleSubmit)}>
6371
<div className="grid gap-4 py-4">
6472
<div className="grid w-full items-center gap-1.5">
6573
<Label htmlFor="first-name">First Name</Label>
@@ -117,11 +125,11 @@ export function CreateAssocUser() {
117125
</div>
118126
<SheetFooter className="mt-4 flex flex-row justify-end items-center">
119127
<SheetClose>
120-
<Button variant="ghost" disabled={isPending}>
128+
<Button variant="ghost" disabled={pending}>
121129
Cancel
122130
</Button>
123131
</SheetClose>
124-
<Button disabled={isPending}>{isPending ? "Saving..." : "Create"}</Button>
132+
<Button disabled={pending}>{pending ? "Saving..." : "Create"}</Button>
125133
</SheetFooter>
126134
</form>
127135
</SheetContent>

src/app/dashboard/(active)/azure/members/page.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@ import Link from "next/link"
33
import { Suspense } from "react"
44
import { ErrorBoundary } from "react-error-boundary"
55
import { Spinner } from "@/components/spinner"
6-
import { getQueryClient, trpc } from "@/lib/trpc/server"
6+
import { getAzureMembers } from "@/server/actions/azure"
77
import { AssocTable } from "./table"
88

99
export default async function AssocMembers() {
10-
const qc = getQueryClient()
11-
void qc.prefetchQuery(trpc.azure.members.getAll.queryOptions())
10+
const members = await getAzureMembers()
11+
1212
return (
1313
<div className="container p-8">
1414
<Link href="/dashboard/azure" className="flex gap-1 items-center text-muted-foreground mb-2 hover:underline">
1515
<ArrowLeft size={16} /> Back
1616
</Link>
1717
<ErrorBoundary fallback={<div>Something went wrong</div>}>
1818
<Suspense fallback={<Spinner />}>
19-
<AssocTable />
19+
<AssocTable members={members} />
2020
</Suspense>
2121
</ErrorBoundary>
2222
</div>

0 commit comments

Comments
 (0)