feat(modules): modules added to frontend

This commit is contained in:
2025-10-30 10:24:04 -05:00
parent 99b2d762d6
commit c552b9eb1c
20 changed files with 4018 additions and 130 deletions

View File

@@ -1,14 +1,14 @@
import { useState } from "react";
import { toast } from "sonner";
import { Button } from "../../../../components/ui/button";
import { Button } from "../../../../../components/ui/button";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "../../../../components/ui/select";
import { api } from "../../../../lib/axiosAPI";
} from "../../../../../components/ui/select";
import { api } from "../../../../../lib/axiosAPI";
const modules: string[] = [
"users",

View File

@@ -0,0 +1,297 @@
import { useMutation, useQuery } from "@tanstack/react-query";
import { createFileRoute } from "@tanstack/react-router";
import {
createColumnHelper,
flexRender,
getCoreRowModel,
getPaginationRowModel,
getSortedRowModel,
//type Row,
type SortingState,
useReactTable,
} from "@tanstack/react-table";
import axios from "axios";
import {
Activity,
ArrowDown,
ArrowUp,
BookOpenCheck,
FolderPen,
} from "lucide-react";
import React, { useState } from "react";
import { Button } from "@/components/ui/button";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { getModules } from "@/lib/querys/admin/getModules";
import { cn } from "@/lib/utils";
import { useModuleStore } from "@/routes/_old/old/-lib/store/useModuleStore";
type Modules = {
category: string;
name: string;
active: boolean;
link: string;
roles: string[];
};
const updateModuleActive = async (module: string, active: boolean) => {
return axios.patch(
`/lst/api/system/modules/update/${module}`,
{ active },
{ withCredentials: true },
);
};
export const Route = createFileRoute(
"/_app/_adminLayout/admin/_system/modules",
)({
component: RouteComponent,
});
function RouteComponent() {
const { data, isLoading, refetch } = useQuery(getModules());
const [sorting, setSorting] = useState<SortingState>([]);
const columnHelper = createColumnHelper<Modules>();
const { fetchModules } = useModuleStore();
const updateActive = useMutation({
mutationFn: ({ module, active }: { module: string; active: boolean }) =>
updateModuleActive(module, active),
onSuccess: () => {
// refetch or update cache
fetchModules();
refetch();
},
});
const columns = [
columnHelper.accessor("category", {
cell: (i) => i.getValue(),
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">
<BookOpenCheck />
Category
</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
columnHelper.accessor("name", {
cell: (i) => i.getValue(),
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">
<FolderPen />
Name
</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
columnHelper.accessor("active", {
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">
<Activity />
Active
</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
cell: ({ row, getValue }) => {
const active = getValue<boolean>();
const module = row.original.name;
const ignoreModules = ["admin", "system", "users"];
return (
<>
{ignoreModules.includes(module) ? (
<></>
) : (
<Select
value={active ? "true" : "false"}
onValueChange={(value) => {
const newValue = value === "true";
updateActive.mutate({ module, active: newValue });
}}
>
<SelectTrigger
className={cn(
"w-[100px]",
active
? "border-green-500 text-green-600"
: "border-gray-400 text-gray-500",
)}
>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="true">True</SelectItem>
<SelectItem value="false">False</SelectItem>
</SelectContent>
</Select>
)}
</>
);
},
}),
columnHelper.accessor("link", {
cell: (i) => i.getValue(),
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
<span className="flex flex-row gap-2">
<FolderPen />
Name
</span>
{column.getIsSorted() === "asc" ? (
<ArrowUp className="ml-2 h-4 w-4" />
) : (
<ArrowDown className="ml-2 h-4 w-4" />
)}
</Button>
);
},
}),
];
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onSortingChange: setSorting,
getSortedRowModel: getSortedRowModel(),
//renderSubComponent: ({ row }: { row: any }) => <ExpandedRow row={row} />,
//getRowCanExpand: () => true,
state: {
sorting,
},
});
if (isLoading) {
return <div className="m-auto">Loading user data</div>;
}
// function renderSubComponent( { row: Row<Modules> }): React.ReactNode {
// throw new Error("Function not implemented.");
// }
//console.log(data);
return (
<div className="p-4">
<div className="w-fit">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</TableHead>
);
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows.map((row) => (
<React.Fragment key={row.id}>
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</TableCell>
))}
</TableRow>
{/* {row.getIsExpanded() && (
<TableRow>
<TableCell colSpan={row.getVisibleCells().length}>
{renderSubComponent({ row })}
</TableCell>
</TableRow>
)} */}
</React.Fragment>
))}
</TableBody>
</Table>
<div className="flex items-center justify-end space-x-2 py-4">
<Button
variant="outline"
size="sm"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
>
Previous
</Button>
<Button
variant="outline"
size="sm"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
>
Next
</Button>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,33 @@
import { createFileRoute, Link, Outlet } from "@tanstack/react-router";
export const Route = createFileRoute("/_app/_adminLayout/admin/_system")({
component: RouteComponent,
});
function RouteComponent() {
return (
<div>
<nav className="flex justify-center gap-3">
<Link
to="/admin/settings"
className="[&.active]:font-bold [&.active]:underline"
activeOptions={{
exact: true,
}}
>
Settings
</Link>
<Link
to="/admin/modules"
className="[&.active]:font-bold [&.active]:underline"
activeOptions={{
exact: true,
}}
>
Modules
</Link>
</nav>
<Outlet />
</div>
);
}

View File

@@ -0,0 +1,11 @@
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute(
'/_app/_adminLayout/admin/_system/settings',
)({
component: RouteComponent,
})
function RouteComponent() {
return <div>Hello "/_app/_adminLayout/admin/_system/settings"!</div>
}

View File

@@ -30,7 +30,7 @@ import {
TableRow,
} from "../../../../../components/ui/table";
import { getUsers } from "../../../../../lib/querys/admin/getUsers";
import ExpandedRow from "../../-components/ExpandedRow";
import ExpandedRow from "../../-components/users/ExpandedRow";
type User = {
username: string;

View File

@@ -1,9 +0,0 @@
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/_app/_adminLayout/admin/settings')({
component: RouteComponent,
})
function RouteComponent() {
return <div>Hello "/_adminLayout/admin/settings"!</div>
}

View File

@@ -15,7 +15,6 @@ import { hasPageAccess } from "../../../-utils/userAccess";
const iconMap: any = {
Printer: Printer,
Tag: Tag,
Cat: Cat,
};
@@ -29,9 +28,8 @@ export function ProductionSideBar({
//const url: string = window.location.host.split(":")[0];
const { modules } = useModuleStore();
const items = modules?.filter((m) => m.category === "production");
const items = modules?.filter((m) => m.category === "production" && m.active);
const userUpdate = { ...user, roles: userRoles };
return (
<SidebarGroup>
<SidebarGroupLabel>Production</SidebarGroupLabel>