Skip to content

Commit

Permalink
feat(ui): Add table component and updated in community validator
Browse files Browse the repository at this point in the history
  • Loading branch information
EdSDR committed Oct 2, 2024
1 parent 37f7af8 commit 54fa2b9
Show file tree
Hide file tree
Showing 3 changed files with 253 additions and 95 deletions.
218 changes: 123 additions & 95 deletions apps/commune-validator/src/app/components/delegated-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@ import { usePathname, useRouter } from "next/navigation";
import { ChevronUpIcon, XMarkIcon } from "@heroicons/react/24/outline";

import { useCommune } from "@commune-ts/providers/use-commune";
import { cn } from "@commune-ts/ui";
import {
cn,
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@commune-ts/ui";
import { formatToken, smallAddress } from "@commune-ts/utils";

import { useDelegateModuleStore } from "~/stores/delegateModuleStore";
Expand Down Expand Up @@ -418,99 +426,115 @@ export function DelegatedList() {
</div>
{isOpen && (
<div className="mb-2 flex animate-fade-up flex-col divide-white/20 rounded-3xl border border-white/20 bg-[#898989]/5 p-4 font-semibold text-white backdrop-blur-md">
<div className="mb-2 grid grid-cols-3 gap-6 border-b border-white/20 pb-2 text-sm font-semibold text-gray-400 md:grid-cols-4">
<div>{activeTab === "modules" ? "Module" : "Subnet"}</div>
<div className="hidden md:block">Name</div>
<div>{activeTab === "modules" ? "Address" : "Founder"}</div>
<div>Percentage</div>
</div>
{activeTab === "modules" ? (
delegatedModules.length ? (
delegatedModules.map((module) => (
<div
key={module.id}
className="mb-2 grid animate-fade-up grid-cols-3 items-center gap-6 border-b border-white/20 pb-2 text-sm animate-delay-100 md:grid-cols-4"
>
<div className="text-white">{module.title}</div>
<div className="hidden text-white md:block">
{module.name}
</div>
<div className="text-gray-400">
{smallAddress(module.address)}
</div>
<div className="flex items-center">
<input
type="number"
value={module.percentage}
onChange={(e) =>
handlePercentageChange(
module.id,
Number(e.target.value),
)
}
className="mr-1 w-12 bg-[#898989]/10 p-1 text-white"
min="0"
max="100"
/>
<span className="mr-2 text-white">%</span>
<button
onClick={() => removeModule(module.id)}
className="ml-2 flex items-center rounded-full bg-red-500/10 p-1 text-red-500 hover:bg-red-500/20 hover:text-red-400"
>
<XMarkIcon className="h-4 w-4" />
</button>
</div>
</div>
))
) : (
<div className="py-6 text-white">
No modules found. Select a module to allocate weight through
the modules page and they will appear here.
</div>
)
) : delegatedSubnets.length ? (
delegatedSubnets.map((subnet) => (
<div
key={subnet.id}
className="mb-2 grid animate-fade-up grid-cols-3 items-center gap-6 border-b border-white/20 pb-2 text-sm animate-delay-100 md:grid-cols-4"
>
<div className="text-white">{subnet.name}</div>
<div className="hidden text-white md:block">
{subnet.name}
</div>
<div className="text-gray-400">
{smallAddress(subnet.founder)}
</div>
<div className="flex items-center">
<input
type="number"
value={subnet.percentage}
onChange={(e) =>
handlePercentageChange(
subnet.id,
Number(e.target.value),
)
}
className="mr-1 w-12 bg-[#898989]/10 p-1 text-white"
min="0"
max="100"
/>
<span className="mr-2 text-white">%</span>
<button
onClick={() => removeSubnet(subnet.id)}
className="ml-2 flex items-center rounded-full bg-red-500/10 p-1 text-red-500 hover:bg-red-500/20 hover:text-red-400"
>
<XMarkIcon className="h-4 w-4" />
</button>
</div>
</div>
))
) : (
<div className="py-6 text-white">
No subnets found. Select a subnet to allocate weight through
the subnets page and they will appear here.
</div>
)}
<Table>
<TableHeader>
<TableRow>
<TableHead>
{activeTab === "modules" ? "Module" : "Subnet"}
</TableHead>
<TableHead className="hidden md:table-cell">Name</TableHead>
<TableHead>
{activeTab === "modules" ? "Address" : "Founder"}
</TableHead>
<TableHead>Percentage</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{activeTab === "modules" ? (
delegatedModules.length ? (
delegatedModules.map((module) => (
<TableRow key={module.id}>
<TableCell className="font-medium">
{module.title}
</TableCell>
<TableCell className="hidden md:table-cell">
{module.name}
</TableCell>
<TableCell className="text-gray-400">
{smallAddress(module.address)}
</TableCell>
<TableCell>
<div className="flex items-center">
<input
type="number"
value={module.percentage}
onChange={(e) =>
handlePercentageChange(
module.id,
Number(e.target.value),
)
}
className="mr-1 w-12 bg-[#898989]/10 p-1 text-white"
min="0"
max="100"
/>
<span className="mr-2 text-white">%</span>
<button
onClick={() => removeModule(module.id)}
className="ml-2 flex items-center rounded-full bg-red-500/10 p-1 text-red-500 hover:bg-red-500/20 hover:text-red-400"
>
<XMarkIcon className="h-4 w-4" />
</button>
</div>
</TableCell>
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={4} className="text-center">
No modules found. Select a module to allocate weight
through the modules page and they will appear here.
</TableCell>
</TableRow>
)
) : delegatedSubnets.length ? (
delegatedSubnets.map((subnet) => (
<TableRow key={subnet.id}>
<TableCell className="font-medium">
{subnet.name}
</TableCell>
<TableCell className="hidden md:table-cell">
{subnet.name}
</TableCell>
<TableCell className="text-gray-400">
{smallAddress(subnet.founder)}
</TableCell>
<TableCell>
<div className="flex items-center">
<input
type="number"
value={subnet.percentage}
onChange={(e) =>
handlePercentageChange(
subnet.id,
Number(e.target.value),
)
}
className="mr-1 w-12 bg-[#898989]/10 p-1 text-white"
min="0"
max="100"
/>
<span className="mr-2 text-white">%</span>
<button
onClick={() => removeSubnet(subnet.id)}
className="ml-2 flex items-center rounded-full bg-red-500/10 p-1 text-red-500 hover:bg-red-500/20 hover:text-red-400"
>
<XMarkIcon className="h-4 w-4" />
</button>
</div>
</TableCell>
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={4} className="text-center">
No subnets found. Select a subnet to allocate weight
through the subnets page and they will appear here.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
<div className="flex flex-row gap-3">
<button
onClick={handleAutoCompletePercentage}
Expand Down Expand Up @@ -538,7 +562,11 @@ export function DelegatedList() {
disabled={submitStatus.disabled}
title={submitStatus.disabled ? submitStatus.message : ""}
>
{isSubmitting ? "Submitting..." : "Submit"}
{isSubmitting
? "Submitting..."
: activeTab === "modules"
? "Submit Modules"
: "Submit Subnets"}
</button>
</div>
</div>
Expand Down
10 changes: 10 additions & 0 deletions packages/ui/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,13 @@ export {
SheetDescription,
} from "./sheet";
export { Tabs, TabsList, TabsTrigger, TabsContent } from "./tabs";
export {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
} from "./table";
120 changes: 120 additions & 0 deletions packages/ui/src/components/table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import * as React from "react";

import { cn } from ".";

const Table = React.forwardRef<
HTMLTableElement,
React.HTMLAttributes<HTMLTableElement>
>(({ className, ...props }, ref) => (
<div className="relative w-full overflow-auto">
<table
ref={ref}
className={cn("w-full caption-bottom text-sm", className)}
{...props}
/>
</div>
));
Table.displayName = "Table";

const TableHeader = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
));
TableHeader.displayName = "TableHeader";

const TableBody = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tbody
ref={ref}
className={cn("[&_tr:last-child]:border-0", className)}
{...props}
/>
));
TableBody.displayName = "TableBody";

const TableFooter = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tfoot
ref={ref}
className={cn(
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
className,
)}
{...props}
/>
));
TableFooter.displayName = "TableFooter";

const TableRow = React.forwardRef<
HTMLTableRowElement,
React.HTMLAttributes<HTMLTableRowElement>
>(({ className, ...props }, ref) => (
<tr
ref={ref}
className={cn(
"border-b border-white/20 transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
className,
)}
{...props}
/>
));
TableRow.displayName = "TableRow";

const TableHead = React.forwardRef<
HTMLTableCellElement,
React.ThHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<th
ref={ref}
className={cn(
"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className,
)}
{...props}
/>
));
TableHead.displayName = "TableHead";

const TableCell = React.forwardRef<
HTMLTableCellElement,
React.TdHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<td
ref={ref}
className={cn(
"p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className,
)}
{...props}
/>
));
TableCell.displayName = "TableCell";

const TableCaption = React.forwardRef<
HTMLTableCaptionElement,
React.HTMLAttributes<HTMLTableCaptionElement>
>(({ className, ...props }, ref) => (
<caption
ref={ref}
className={cn("mt-4 text-sm text-muted-foreground", className)}
{...props}
/>
));
TableCaption.displayName = "TableCaption";

export {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
};

0 comments on commit 54fa2b9

Please sign in to comment.