完成了一些接口

This commit is contained in:
2025-05-12 12:07:01 +08:00
parent d8fd52d73e
commit 7a4855d131
7 changed files with 148 additions and 12 deletions

View File

@@ -20,6 +20,12 @@ import { Skeleton } from "@/components/ui/skeleton";
import { updateUser } from "@/lib/api/admin/user"; import { updateUser } from "@/lib/api/admin/user";
import { AdminApi } from "@/lib/api"; import { AdminApi } from "@/lib/api";
import { toast } from "sonner"; import { toast } from "sonner";
import {
Alert,
AlertDescription,
AlertTitle,
} from "@/components/ui/alert"
import { AlertCircle } from "lucide-react";
export function UserInfoEditor({ export function UserInfoEditor({
onClose, onClose,
@@ -46,6 +52,14 @@ export function UserInfoEditor({
} }
} }
const handleRemove = async () => {
}
const handleSetPassword = async () => {
}
return ( return (
<Drawer open={!!userId} onClose={onClose} > <Drawer open={!!userId} onClose={onClose} >
<DrawerContent> <DrawerContent>
@@ -54,7 +68,11 @@ export function UserInfoEditor({
<DrawerDescription></DrawerDescription> <DrawerDescription></DrawerDescription>
</DrawerHeader> </DrawerHeader>
{user && <ProfileForm className="px-4" user={user} onSubmit={(e) => { {user && <ProfileForm className="px-4"
user={user}
onSetPassword={handleSetPassword}
onRemove={handleRemove}
onSubmit={(e) => {
e.preventDefault() e.preventDefault()
const formData = new FormData(e.currentTarget); const formData = new FormData(e.currentTarget);
handleSave({ handleSave({
@@ -71,6 +89,16 @@ export function UserInfoEditor({
)) ))
} }
{
error && (
<Alert variant="destructive" className="mx-4">
<AlertCircle className="h-6 w-6" />
<AlertTitle>!</AlertTitle>
<AlertDescription>{error.message}</AlertDescription>
</Alert>
)
}
<DrawerFooter className="pt-2"> <DrawerFooter className="pt-2">
<DrawerClose asChild> <DrawerClose asChild>
<Button variant="outline"></Button> <Button variant="outline"></Button>
@@ -81,7 +109,12 @@ export function UserInfoEditor({
) )
} }
function ProfileForm({ className, user, ...props }: React.ComponentProps<"form"> & { user: User }) { function ProfileForm({ className, user, onSetPassword, onRemove, ...props }:
React.ComponentProps<"form"> & {
user: User,
onSetPassword: () => Promise<void>,
onRemove: () => Promise<void>,
}) {
return ( return (
<form className={cn("grid items-start gap-4", className)} {...props}> <form className={cn("grid items-start gap-4", className)} {...props}>
<div className="grid gap-2"> <div className="grid gap-2">
@@ -104,6 +137,10 @@ function ProfileForm({ className, user, ...props }: React.ComponentProps<"form">
<Label htmlFor="phone"></Label> <Label htmlFor="phone"></Label>
<Input id="phone" name="phone" defaultValue={user.phone} /> <Input id="phone" name="phone" defaultValue={user.phone} />
</div> </div>
<div className="w-full flex gap-5">
<Button type="button" variant="secondary" className="flex-1" onClick={onSetPassword}></Button>
<Button type="button" variant="destructive" className="flex-1" onClick={onRemove}></Button>
</div>
<Button type="submit"></Button> <Button type="submit"></Button>
</form> </form>
) )

View File

@@ -0,0 +1,66 @@
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const alertVariants = cva(
"relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
{
variants: {
variant: {
default: "bg-card text-card-foreground",
destructive:
"text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
},
},
defaultVariants: {
variant: "default",
},
}
)
function Alert({
className,
variant,
...props
}: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
return (
<div
data-slot="alert"
role="alert"
className={cn(alertVariants({ variant }), className)}
{...props}
/>
)
}
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="alert-title"
className={cn(
"col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight",
className
)}
{...props}
/>
)
}
function AlertDescription({
className,
...props
}: React.ComponentProps<"div">) {
return (
<div
data-slot="alert-description"
className={cn(
"text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed",
className
)}
{...props}
/>
)
}
export { Alert, AlertTitle, AlertDescription }

View File

@@ -2,3 +2,4 @@ export * from './list';
export * from './get'; export * from './get';
export * from './create'; export * from './create';
export * from './update'; export * from './update';
export * from './set-password';

View File

@@ -0,0 +1,7 @@
import fetcher from "../../fetcher";
export async function remove(userId: string) {
return fetcher(`/admin/user/${userId}`, {
method: 'DELETE',
})
}

View File

@@ -0,0 +1,10 @@
import fetcher from "../../fetcher";
export async function setPassword(userId: string, password: string) {
return fetcher(`/admin/user/${userId}/password`, {
method: 'POST',
body: JSON.stringify({
password,
}),
})
}

View File

@@ -20,6 +20,7 @@
"@radix-ui/react-separator": "^1.1.6", "@radix-ui/react-separator": "^1.1.6",
"@radix-ui/react-slot": "^1.2.0", "@radix-ui/react-slot": "^1.2.0",
"@radix-ui/react-tooltip": "^1.2.6", "@radix-ui/react-tooltip": "^1.2.6",
"alert": "^6.0.2",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"dialog": "^0.3.1", "dialog": "^0.3.1",

View File

@@ -41,6 +41,9 @@ importers:
'@radix-ui/react-tooltip': '@radix-ui/react-tooltip':
specifier: ^1.2.6 specifier: ^1.2.6
version: 1.2.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) version: 1.2.6(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
alert:
specifier: ^6.0.2
version: 6.0.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
class-variance-authority: class-variance-authority:
specifier: ^0.7.1 specifier: ^0.7.1
version: 0.7.1 version: 0.7.1
@@ -1227,6 +1230,12 @@ packages:
ajv@6.12.6: ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
alert@6.0.2:
resolution: {integrity: sha512-Oi8u2HRNN6mzpjgKGii2Uuf9iOhyfbeUAHH/5MwnVmC8DS9GrEBjZBFpoavkNj+ZKnBr/Lqx+6YKLDKrggKfPA==}
peerDependencies:
react: ^18.0.0
react-dom: ^18.0.0
ansi-styles@4.3.0: ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -3509,6 +3518,11 @@ snapshots:
json-schema-traverse: 0.4.1 json-schema-traverse: 0.4.1
uri-js: 4.4.1 uri-js: 4.4.1
alert@6.0.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
ansi-styles@4.3.0: ansi-styles@4.3.0:
dependencies: dependencies:
color-convert: 2.0.1 color-convert: 2.0.1