mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-13 21:05:22 +00:00
action button styling in settings and toast on copy
This commit is contained in:
parent
8ad6ba7ab0
commit
258585e981
4 changed files with 68 additions and 5 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { DataTable } from "@/components/ui/data-table";
|
import { DataTable } from "@/components/ui/data-table";
|
||||||
import { InviteColumnInfo, inviteTableColumns } from "./inviteTableColumns"
|
import { InviteColumnInfo, inviteTableColumns } from "./inviteTableColumns"
|
||||||
|
import { useToast } from "@/components/hooks/use-toast";
|
||||||
|
|
||||||
export interface InviteInfo {
|
export interface InviteInfo {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -14,6 +15,14 @@ interface InviteTableProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const InviteTable = ({ initialInvites }: InviteTableProps) => {
|
export const InviteTable = ({ initialInvites }: InviteTableProps) => {
|
||||||
|
const { toast } = useToast();
|
||||||
|
|
||||||
|
const displayToast = (message: string) => {
|
||||||
|
toast({
|
||||||
|
description: message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const inviteRows: InviteColumnInfo[] = useMemo(() => {
|
const inviteRows: InviteColumnInfo[] = useMemo(() => {
|
||||||
return initialInvites.map(invite => {
|
return initialInvites.map(invite => {
|
||||||
return {
|
return {
|
||||||
|
|
@ -28,7 +37,7 @@ export const InviteTable = ({ initialInvites }: InviteTableProps) => {
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<h4 className="text-lg font-normal">Invites</h4>
|
<h4 className="text-lg font-normal">Invites</h4>
|
||||||
<DataTable
|
<DataTable
|
||||||
columns={inviteTableColumns()}
|
columns={inviteTableColumns(displayToast)}
|
||||||
data={inviteRows}
|
data={inviteRows}
|
||||||
searchKey="email"
|
searchKey="email"
|
||||||
searchPlaceholder="Search invites..."
|
searchPlaceholder="Search invites..."
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { Button } from "@/components/ui/button";
|
||||||
import { ColumnDef } from "@tanstack/react-table"
|
import { ColumnDef } from "@tanstack/react-table"
|
||||||
import { resolveServerPath } from "@/app/api/(client)/client";
|
import { resolveServerPath } from "@/app/api/(client)/client";
|
||||||
import { createPathWithQueryParams } from "@/lib/utils";
|
import { createPathWithQueryParams } from "@/lib/utils";
|
||||||
|
import { useToast } from "@/components/hooks/use-toast";
|
||||||
|
|
||||||
export type InviteColumnInfo = {
|
export type InviteColumnInfo = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -11,7 +12,7 @@ export type InviteColumnInfo = {
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const inviteTableColumns = (): ColumnDef<InviteColumnInfo>[] => {
|
export const inviteTableColumns = (displayToast: (message: string) => void): ColumnDef<InviteColumnInfo>[] => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
accessorKey: "email",
|
accessorKey: "email",
|
||||||
|
|
@ -28,19 +29,36 @@ export const inviteTableColumns = (): ColumnDef<InviteColumnInfo>[] => {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "copy",
|
id: "copy",
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const invite = row.original;
|
const invite = row.original;
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
variant="link"
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const basePath = `${window.location.origin}${resolveServerPath('/')}`;
|
const basePath = `${window.location.origin}${resolveServerPath('/')}`;
|
||||||
const url = createPathWithQueryParams(`${basePath}redeem?invite_id=${invite.id}`);
|
const url = createPathWithQueryParams(`${basePath}redeem?invite_id=${invite.id}`);
|
||||||
navigator.clipboard.writeText(url);
|
navigator.clipboard.writeText(url);
|
||||||
|
|
||||||
|
displayToast("✅ Copied invite link");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Copy
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
className="hover:stroke-gray-600 transition-colors"
|
||||||
|
>
|
||||||
|
<rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
|
||||||
|
<path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
|
||||||
|
</svg>
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,14 @@ import { createInvite } from "@/actions"
|
||||||
import { isServiceError } from "@/lib/utils";
|
import { isServiceError } from "@/lib/utils";
|
||||||
import { useDomain } from "@/hooks/useDomain";
|
import { useDomain } from "@/hooks/useDomain";
|
||||||
import { ErrorCode } from "@/lib/errorCodes";
|
import { ErrorCode } from "@/lib/errorCodes";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
email: z.string().min(2).max(40),
|
email: z.string().min(2).max(40),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const MemberInviteForm = ({ userId }: { userId: string }) => {
|
export const MemberInviteForm = ({ userId }: { userId: string }) => {
|
||||||
|
const router = useRouter();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const domain = useDomain();
|
const domain = useDomain();
|
||||||
|
|
||||||
|
|
@ -37,6 +39,8 @@ export const MemberInviteForm = ({ userId }: { userId: string }) => {
|
||||||
toast({
|
toast({
|
||||||
description: `✅ Invite created successfully!`
|
description: `✅ Invite created successfully!`
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
import { ColumnDef } from "@tanstack/react-table"
|
import { ColumnDef } from "@tanstack/react-table"
|
||||||
|
|
||||||
export type MemberColumnInfo = {
|
export type MemberColumnInfo = {
|
||||||
|
|
@ -22,6 +23,37 @@ export const memberTableColumns = (): ColumnDef<MemberColumnInfo>[] => {
|
||||||
const member = row.original;
|
const member = row.original;
|
||||||
return <div>{member.role}</div>;
|
return <div>{member.role}</div>;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "remove",
|
||||||
|
cell: () => {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
onClick={() => {
|
||||||
|
// TODO: Implement remove member action
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
className="text-red-400 hover:text-red-600 transition-colors"
|
||||||
|
>
|
||||||
|
<path d="M3 6h18" />
|
||||||
|
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
|
||||||
|
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
|
||||||
|
</svg>
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue