feat: copy button

This commit is contained in:
SevicheCC 2023-06-06 02:47:14 +08:00
parent ae0fc58569
commit c2900df6e9
Signed by: SevicheCC
GPG key ID: C577000000000000
9 changed files with 102 additions and 45 deletions

View file

@ -8,7 +8,7 @@ import {
CardHeader,
CardTitle,
} from "@/components/ui/card";
import DataDisplay from "@/components/DataDisplay";
import FormContainer from "@/components/FormContainer";
export default function Home() {
return (
@ -19,21 +19,15 @@ export default function Home() {
<CardTitle>M-OAuth</CardTitle>
<CardDescription>Card Description</CardDescription>
</CardHeader>
<CardContent>
<ClientOnly>
<InputForm />
<FormContainer/>
</ClientOnly>
</CardContent>
{/* <CardFooter>
<p>Card Footer</p>
</CardFooter> */}
</Card>
<Card>
<CardContent>
<DataDisplay />
</CardContent>
</Card>
</div>
</main>
);

View file

@ -1,40 +1,44 @@
'use client'
"use client";
import useCreateApp from "@/hooks/useCreateApp";
import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { AppEntry } from "../lib/types";
interface DataDisplayProps {
appEntry: AppEntry;
}
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { AppEntry } from "@/lib/types";
import { CopyButton } from "./ui/copybutton";
const renderTableRow = (label: string, value: string | undefined) => (
<TableRow>
<TableRow className="group relative">
<TableCell className="font-medium">{label}</TableCell>
<TableCell>{value}</TableCell>
<TableCell className="font-mono break-all flex justify-between items-center">
{value}
{value && <CopyButton value={value} className="end-2 shrink-0"/>}
</TableCell>
</TableRow>
);
const DataDisplay = () => {
const { appEntry } = useCreateApp();
const DataDisplay = ({ appEntry }: { appEntry: AppEntry }) => {
return (
<Table>
<TableCaption>A list of your recent invoices.</TableCaption>
<TableHeader>
<TableRow>
<TableHead>Data Name</TableHead>
<TableHead className="min-w-[120px]">Type</TableHead>
<TableHead>Value</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{renderTableRow("ID", appEntry?.id)}
{renderTableRow("Name", appEntry?.name)}
{renderTableRow("Website", appEntry?.website || '')}
{renderTableRow("Redirect URI", appEntry?.redirectUri)}
{renderTableRow("Client ID", appEntry?.clientId)}
{renderTableRow("Client Secret", appEntry?.clientSecret)}
{renderTableRow("Vapid Key", appEntry?.vapidKey)}
{renderTableRow("Website", appEntry?.website || "")}
{renderTableRow("Redirect URI", appEntry?.redirect_uri)}
{renderTableRow("Client ID", appEntry?.client_id)}
{renderTableRow("Client Secret", appEntry?.client_secret)}
{renderTableRow("Vapid Key", appEntry?.vapid_key)}
</TableBody>
</Table>
);

View file

@ -0,0 +1,16 @@
"use client";
import InputForm from "@/components/InputForm";
import DataDisplay from "@/components/DataDisplay";
import useCreateApp from "@/hooks/useCreateApp";
const FormContainer = () => {
const { appEntry, createApp } = useCreateApp();
return (
<>
<InputForm createApp={createApp} />
{appEntry && <DataDisplay appEntry={appEntry} />}
</>
);
};
export default FormContainer;

View file

@ -15,9 +15,8 @@ import {
FormMessage,
} from "@/components/ui/form";
import ScopeSection from "@/components/ScopeSection";
import ScopeSection from "@/components/scopes/ScopeSection";
import { scopesInfo } from "@/lib/utils";
import useCreateApp from "@/hooks/useCreateApp";
const formSchema = z.object({
instance: z.string().trim(),
@ -28,9 +27,11 @@ const formSchema = z.object({
});
export type FormSchema = z.infer<typeof formSchema>;
interface InputFormProps {
createApp: ({}: FormSchema) => Promise<void>;
}
const InputForm = () => {
const { createApp } = useCreateApp();
const InputForm: React.FC<InputFormProps> = ({ createApp }) => {
const form = useForm<FormSchema>({
resolver: zodResolver(formSchema),
defaultValues: {
@ -43,7 +44,10 @@ const InputForm = () => {
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(createApp)} className="space-y-6 flex flex-col">
<form
onSubmit={form.handleSubmit(createApp)}
className="flex flex-col space-y-6 mb-6"
>
<FormField
control={form.control}
name="instance"
@ -132,7 +136,9 @@ const InputForm = () => {
</FormItem>
)}
/>
<Button type="submit" className="w-ful">Submit</Button>
<Button type="submit" className="w-ful">
Submit
</Button>
</form>
</Form>
);

View file

@ -8,7 +8,7 @@ import {
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { Button } from "@/components/ui/button";
import ScopeItem from "@/components/ScopeItem";
import ScopeItem from "@/components/scopes/ScopeItem";
import { ScopeInfo } from "@/lib/types";

View file

@ -0,0 +1,40 @@
"use client";
import { useEffect, useState } from "react";
import { cn } from "@/lib/utils";
import { Check, Copy } from "lucide-react";
interface CopyButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
value: string;
}
const copyToClipboardWithMeta = (value: string, event?: Event) => {
navigator.clipboard.writeText(value);
};
export function CopyButton({ value, className, ...props }: CopyButtonProps) {
const [hasCopied, setHasCopied] = useState(false);
useEffect(() => {
setTimeout(() => {
setHasCopied(false);
}, 2000);
}, [hasCopied]);
return (
<button
className={cn(
"z-20 inline-flex h-8 w-8 items-center justify-center rounded-md border bg-background text-sm font-medium transition-all hover:bg-muted focus:outline-none ",
className
)}
onClick={() => {
copyToClipboardWithMeta(value);
setHasCopied(true);
}}
{...props}
>
<span className="sr-only">Copy</span>
{hasCopied ? <Check className="h-3 w-3" /> : <Copy className="h-3 w-3" />}
</button>
);
}

View file

@ -24,7 +24,6 @@ const useCreateApp = () => {
scopes: scopes?.join(" "),
};
console.log("app,", app);
try {
let request = await fetch(`${instance}/api/v1/apps`, {
method: "POST",
@ -41,10 +40,9 @@ const useCreateApp = () => {
} catch (error) {
throw new Error((error as MError).error);
}
},
[]
},[]
);
console.log(appEntry);
return {
appEntry,
createApp,

View file

@ -18,10 +18,9 @@ export interface ScopeInfo {
id: string;
name: string;
website: string | null;
redirectUri: string;
clientId: string;
clientSecret: string;
vapidKey: string;
redirect_uri: string;
client_id: string;
client_secret: string;
vapid_key: string;
}