Updates
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { useMemo, useState, type Dispatch, type SetStateAction } from "react";
|
||||
import Search from "@/src/components/twui/elements/Search";
|
||||
import AdminCard from "@/src/components/general/admin-card";
|
||||
import ClientRow from "../(partials)/client-row";
|
||||
import ClientFormModal from "../(partials)/client-form-modal";
|
||||
import { CLIENTS } from "../(data)/clients-mock-data";
|
||||
|
||||
type Props = {
|
||||
addOpen: boolean;
|
||||
setAddOpen: Dispatch<SetStateAction<boolean>>;
|
||||
};
|
||||
|
||||
const thClass =
|
||||
"px-4 py-2 text-left text-[11px] font-semibold uppercase tracking-[0.08em] " +
|
||||
"text-foreground-light/40 dark:text-foreground-dark/40 whitespace-nowrap";
|
||||
|
||||
const thRightClass = `${thClass} text-right`;
|
||||
|
||||
export default function ClientsTableSection({ addOpen, setAddOpen }: Props) {
|
||||
const [query, setQuery] = useState("");
|
||||
|
||||
const filtered = useMemo(() => {
|
||||
const q = query.trim().toLowerCase();
|
||||
if (!q) return CLIENTS;
|
||||
return CLIENTS.filter((client) =>
|
||||
[client.name, client.tunnelIp, client.allowedIps].some((value) =>
|
||||
value.toLowerCase().includes(q),
|
||||
),
|
||||
);
|
||||
}, [query]);
|
||||
|
||||
return (
|
||||
<AdminCard className="w-full overflow-hidden">
|
||||
<div className="flex items-center justify-between gap-3 px-5 h-12 flex-wrap">
|
||||
<h2 className="text-[13.5px] font-medium text-foreground-light/60 dark:text-foreground-dark/60">
|
||||
Clients
|
||||
<span className="tabular text-foreground-light/40 dark:text-foreground-dark/40 ml-2">
|
||||
{filtered.length}
|
||||
</span>
|
||||
</h2>
|
||||
<Search
|
||||
no_search_button
|
||||
placeholder="Search clients…"
|
||||
changeHandler={(value) => setQuery(value || "")}
|
||||
inputProps={{
|
||||
className: "!text-[13.5px]",
|
||||
wrapperProps: {
|
||||
className:
|
||||
"!py-[5px] !min-h-[30px] w-[220px] bg-foreground-light/[0.02] dark:bg-foreground-dark/[0.03]",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{filtered.length ? (
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full min-w-[860px]">
|
||||
<thead>
|
||||
<tr className="border-y border-slate-200 dark:border-white/10 bg-foreground-light/[0.02] dark:bg-foreground-dark/[0.03]">
|
||||
<th className={thClass}>Client</th>
|
||||
<th className={thClass}>Tunnel IP</th>
|
||||
<th className={thClass}>Allowed IPs</th>
|
||||
<th className={thClass}>Public key</th>
|
||||
<th className={thRightClass}>Traffic</th>
|
||||
<th className={thRightClass}>Last handshake</th>
|
||||
<th className={thRightClass}>Created</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{filtered.map((client) => (
|
||||
<ClientRow key={client.id} client={client} />
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col items-center justify-center gap-1 py-14 px-6 text-center">
|
||||
<span className="text-[13.5px] font-medium text-foreground-light/50 dark:text-foreground-dark/50">
|
||||
No clients found
|
||||
</span>
|
||||
<span className="text-[12.5px] text-foreground-light/35 dark:text-foreground-dark/35">
|
||||
Try adjusting your search terms
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<ClientFormModal open={addOpen} setOpen={setAddOpen} />
|
||||
</AdminCard>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user