feat: 添加账户信息、通行证注册功能
This commit is contained in:
@@ -1,5 +1,217 @@
|
||||
'use client';
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Field, FieldDescription, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet } from "@/components/ui/field";
|
||||
import { useUserStore } from "@/store/useUserStore";
|
||||
import { Checkbox } from "@radix-ui/react-checkbox";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCaption,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table"
|
||||
import { ReactElement, useMemo, useState } from "react";
|
||||
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 { AuthAPI } from "@/lib/api/client";
|
||||
import { GeneralErrorHandler, handleAPIError } from "@/lib/api/common";
|
||||
import { startRegistration } from '@simplewebauthn/browser';
|
||||
import { toast } from "sonner";
|
||||
|
||||
export default function Page() {
|
||||
const userStore = useUserStore();
|
||||
const user = userStore.user;
|
||||
|
||||
return (
|
||||
<div></div>
|
||||
<div className="w-full">
|
||||
<form onSubmit={e => {
|
||||
e.preventDefault();
|
||||
}}>
|
||||
<FieldGroup className="gap-5">
|
||||
<FieldSet>
|
||||
<FieldLegend>账户基础信息</FieldLegend>
|
||||
<FieldDescription>这是当前账户的基础信息</FieldDescription>
|
||||
<FieldGroup className="gap-5">
|
||||
{
|
||||
[
|
||||
{
|
||||
name: 'username',
|
||||
localName: '用户名',
|
||||
required: true,
|
||||
defaultValue: user?.username,
|
||||
},
|
||||
{
|
||||
name: 'nickname',
|
||||
localName: '昵称',
|
||||
required: true,
|
||||
defaultValue: user?.nickname,
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
localName: '电子邮箱',
|
||||
required: false,
|
||||
defaultValue: user?.email,
|
||||
},
|
||||
{
|
||||
name: 'phone',
|
||||
localName: '手机号',
|
||||
required: false,
|
||||
defaultValue: user?.phone,
|
||||
description: '当前仅支持中国大陆(+86)手机号'
|
||||
},
|
||||
].map(({ name, localName, required, defaultValue, description }) => (
|
||||
<Field key={name} className="gap-2">
|
||||
<FieldLabel htmlFor={`console-profile-${name}`} className="text-zinc-800">
|
||||
{localName}
|
||||
</FieldLabel>
|
||||
<Input
|
||||
id={`console-profile-${name}`}
|
||||
name={name}
|
||||
defaultValue={defaultValue}
|
||||
placeholder={localName}
|
||||
required={required}
|
||||
disabled
|
||||
/>
|
||||
{
|
||||
description && (
|
||||
<FieldDescription>
|
||||
{description}
|
||||
</FieldDescription>
|
||||
)
|
||||
}
|
||||
</Field>
|
||||
))
|
||||
}
|
||||
</FieldGroup>
|
||||
</FieldSet>
|
||||
<Field orientation="horizontal">
|
||||
<Button type="submit" disabled>保存</Button>
|
||||
<Button variant="outline" type="button" disabled>
|
||||
编辑
|
||||
</Button>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</form>
|
||||
<FieldSeparator className="mt-2 mb-2" />
|
||||
<FieldGroup className="gap-5">
|
||||
<FieldSet>
|
||||
<FieldLegend>通行证列表</FieldLegend>
|
||||
<FieldDescription>
|
||||
通行证(PassKey),一种先进的无密码身份验证技术。
|
||||
</FieldDescription>
|
||||
<PasskeyList />
|
||||
<div>
|
||||
<AddPasskeyDialog>
|
||||
<Button>添加通行证</Button>
|
||||
</AddPasskeyDialog>
|
||||
</div>
|
||||
</FieldSet>
|
||||
</FieldGroup>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
interface AddPasskeyDialogProps {
|
||||
children: ReactElement;
|
||||
}
|
||||
function AddPasskeyDialog({ children }: AddPasskeyDialogProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleSubmit = async (name: string) => {
|
||||
try {
|
||||
name = name.trim();
|
||||
if (name.length === 0) {
|
||||
throw new Error('通行证名称不能为空')
|
||||
}
|
||||
|
||||
const options = await AuthAPI.getPasskeyRegisterOptions();
|
||||
|
||||
const credential = await startRegistration({ optionsJSON: options }).catch(() => null);
|
||||
|
||||
if (credential === null) {
|
||||
throw new Error('认证超时');
|
||||
}
|
||||
|
||||
const registerRes = await AuthAPI.passkeyRegister(name, credential);
|
||||
if (registerRes.id) {
|
||||
toast.success('添加成功');
|
||||
setOpen(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
handleAPIError(error, GeneralErrorHandler);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
{children}
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-100">
|
||||
<DialogHeader>
|
||||
<DialogTitle>添加通行证</DialogTitle>
|
||||
<DialogDescription>
|
||||
如果能添加成功,则说明您的设备支持;如果添加失败了,说明您的设备不支持😊
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<form onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(e.currentTarget);
|
||||
handleSubmit(formData.get('name')?.toString() || '');
|
||||
}}>
|
||||
<div className="grid gap-4">
|
||||
<div className="grid gap-3">
|
||||
<Label htmlFor="console-add-passkey-name">通行证名称</Label>
|
||||
<Input id="console-add-passkey-name" name="name" required />
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter className="mt-6">
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline">取消</Button>
|
||||
</DialogClose>
|
||||
<Button type="submit">下一步</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog >
|
||||
)
|
||||
}
|
||||
|
||||
function PasskeyList() {
|
||||
return (
|
||||
<Table>
|
||||
{/* <TableCaption>A list of your recent invoices.</TableCaption> */}
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>名称</TableHead>
|
||||
<TableHead>状态</TableHead>
|
||||
<TableHead>创建时间</TableHead>
|
||||
<TableHead className="text-right">操作</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell className="font-medium">INV001</TableCell>
|
||||
<TableCell>Paid</TableCell>
|
||||
<TableCell>Credit Card</TableCell>
|
||||
<TableCell className="text-right">$250.00</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user