refactor(front end): login fixes to account for the forced password change

This commit is contained in:
2025-10-21 20:27:00 -05:00
parent 43abbd53f4
commit e99c409cad
26 changed files with 10435 additions and 8732 deletions

View File

@@ -0,0 +1,32 @@
meta {
name: Get Roles
type: http
seq: 2
}
get {
url: {{urlv2}}/api/auth/getuseraccess
body: none
auth: inherit
}
headers {
Content-Type: application/json
Cookie: {{session_cookie}}
}
body:json {
{
"username": "matthes01",
"password": "{{v2Password}}"
}
}
script:post-response {
bru.setEnvVar("jwtV2",res.body.token)
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -22,9 +22,19 @@ body:json {
}
script:post-response {
bru.setEnvVar("jwtV2",res.body.token)
// grab the raw Set-Cookie header
const cookies = res.headers["set-cookie"];
// cookies is usually an array, e.g. ["auth_session=abcd123; Path=/; HttpOnly; Secure; SameSite=Lax"]
// Extract just the value part ("auth_session=abcd123")
const sessionCookie = cookies[0].split(";")[0];
// Save it as an environment variable
bru.setEnvVar("session_cookie", sessionCookie);
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -6,17 +6,11 @@ meta {
get {
url: {{url}}/lst/api/user/roles
body: json
body: none
auth: inherit
}
body:json {
{
"module":"users",
"role":"admin"
}
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -0,0 +1,35 @@
meta {
name: Login
type: http
seq: 10
}
post {
url: {{url}}/lst/api/user/login
body: json
auth: inherit
}
body:json {
{
"username": "cowch",
"password": "Alpla2025!"
}
}
script:post-response {
// grab the raw Set-Cookie header
const cookies = res.headers["set-cookie"];
const sessionCookie = cookies[0].split(";")[0];
// Save it as an environment variable
bru.setEnvVar("session_cookie", sessionCookie);
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -21,4 +21,5 @@ body:json {
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -32,4 +32,5 @@ script:post-response {
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -5,7 +5,7 @@ meta {
}
post {
url: {{url}}/lst/api/auth/session
url: {{url}}/lst/api/auth/sign-out
body: none
auth: inherit
}
@@ -25,4 +25,5 @@ script:post-response {
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -13,12 +13,12 @@ post {
body:json {
{
"scannerId": 999,
"lotNr": 26321,
"machineId": 3, // 457=22, 458=23
"printerId": 7, // 457=22, 458=23
"layoutId": 25,
"lotNr": 3314,
"machineId": 22, // 457=22, 458=23
"printerId": 22, // 457=22, 458=23
"layoutId": 7,
"numberOfCopies": 0,
"qtyToPrint": 30
"qtyToPrint": 3
}
}

View File

@@ -1,8 +1,9 @@
vars {
url: http://localhost:5500
session_cookie:
urlv2: http://usmcd1vms036:3000
urlv2: http://localhost:3000
jwtV2:
userID:
}
vars:secret [
v2Password

View File

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

View File

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

View File

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

View File

@@ -1,15 +0,0 @@
import * as React from 'react'
import { Outlet, createRootRoute } from '@tanstack/react-router'
export const Route = createRootRoute({
component: RootComponent,
})
function RootComponent() {
return (
<React.Fragment>
<div>Hello "__root"!</div>
<Outlet />
</React.Fragment>
)
}

View File

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

View File

@@ -47,9 +47,7 @@ export default function Nav() {
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem>
{/* <Link to="/passwordChange">
Password Change
</Link> */}
<Link to="/user/profile">Profile</Link>
</DropdownMenuItem>
{/* <DropdownMenuItem>Billing</DropdownMenuItem>
<DropdownMenuItem>Team</DropdownMenuItem>

View File

@@ -15,11 +15,13 @@ import { Route as AdminLayoutRouteRouteImport } from './routes/_adminLayout/rout
import { Route as IndexRouteImport } from './routes/index'
import { Route as authLoginRouteImport } from './routes/(auth)/login'
import { Route as mobileStuffMobileLayoutRouteRouteImport } from './routes/(mobileStuff)/_mobileLayout/route'
import { Route as authUserIndexRouteImport } from './routes/(auth)/user/index'
import { Route as AdminLayoutAdminSettingsRouteImport } from './routes/_adminLayout/admin/settings'
import { Route as AdminLayoutAdminServersRouteImport } from './routes/_adminLayout/admin/servers'
import { Route as logisticsLogisticsDeliveryScheduleRouteImport } from './routes/(logistics)/logistics/deliverySchedule'
import { Route as authUserSignupRouteImport } from './routes/(auth)/user/signup'
import { Route as authUserResetpasswordRouteImport } from './routes/(auth)/user/resetpassword'
import { Route as authUserProfileRouteImport } from './routes/(auth)/user/profile'
import { Route as AdminLayoutAdminUsersRouteRouteImport } from './routes/_adminLayout/admin/_users/route'
import { Route as mobileStuffMobileLayoutMIndexRouteImport } from './routes/(mobileStuff)/_mobileLayout/m/index'
import { Route as AdminLayoutAdminUsersUsersRouteImport } from './routes/_adminLayout/admin/_users/users'
@@ -59,6 +61,11 @@ const mobileStuffMobileLayoutRouteRoute =
id: '/_mobileLayout',
getParentRoute: () => mobileStuffRoute,
} as any)
const authUserIndexRoute = authUserIndexRouteImport.update({
id: '/(auth)/user/',
path: '/user/',
getParentRoute: () => rootRouteImport,
} as any)
const AdminLayoutAdminSettingsRoute =
AdminLayoutAdminSettingsRouteImport.update({
id: '/settings',
@@ -86,6 +93,11 @@ const authUserResetpasswordRoute = authUserResetpasswordRouteImport.update({
path: '/user/resetpassword',
getParentRoute: () => rootRouteImport,
} as any)
const authUserProfileRoute = authUserProfileRouteImport.update({
id: '/(auth)/user/profile',
path: '/user/profile',
getParentRoute: () => rootRouteImport,
} as any)
const AdminLayoutAdminUsersRouteRoute =
AdminLayoutAdminUsersRouteRouteImport.update({
id: '/_users',
@@ -132,11 +144,13 @@ export interface FileRoutesByFullPath {
'/': typeof mobileStuffMobileLayoutRouteRouteWithChildren
'/login': typeof authLoginRoute
'/admin': typeof AdminLayoutAdminUsersRouteRouteWithChildren
'/user/profile': typeof authUserProfileRoute
'/user/resetpassword': typeof authUserResetpasswordRoute
'/user/signup': typeof authUserSignupRoute
'/logistics/deliverySchedule': typeof logisticsLogisticsDeliveryScheduleRoute
'/admin/servers': typeof AdminLayoutAdminServersRoute
'/admin/settings': typeof AdminLayoutAdminSettingsRoute
'/user': typeof authUserIndexRoute
'/m/cyclecounts': typeof mobileStuffMobileLayoutMCyclecountsRoute
'/m/delivery': typeof mobileStuffMobileLayoutMDeliveryRoute
'/m/relocate': typeof mobileStuffMobileLayoutMRelocateRoute
@@ -148,11 +162,13 @@ export interface FileRoutesByTo {
'/': typeof mobileStuffMobileLayoutRouteRouteWithChildren
'/login': typeof authLoginRoute
'/admin': typeof AdminLayoutAdminUsersRouteRouteWithChildren
'/user/profile': typeof authUserProfileRoute
'/user/resetpassword': typeof authUserResetpasswordRoute
'/user/signup': typeof authUserSignupRoute
'/logistics/deliverySchedule': typeof logisticsLogisticsDeliveryScheduleRoute
'/admin/servers': typeof AdminLayoutAdminServersRoute
'/admin/settings': typeof AdminLayoutAdminSettingsRoute
'/user': typeof authUserIndexRoute
'/m/cyclecounts': typeof mobileStuffMobileLayoutMCyclecountsRoute
'/m/delivery': typeof mobileStuffMobileLayoutMDeliveryRoute
'/m/relocate': typeof mobileStuffMobileLayoutMRelocateRoute
@@ -169,11 +185,13 @@ export interface FileRoutesById {
'/(auth)/login': typeof authLoginRoute
'/_adminLayout/admin': typeof AdminLayoutAdminRouteWithChildren
'/_adminLayout/admin/_users': typeof AdminLayoutAdminUsersRouteRouteWithChildren
'/(auth)/user/profile': typeof authUserProfileRoute
'/(auth)/user/resetpassword': typeof authUserResetpasswordRoute
'/(auth)/user/signup': typeof authUserSignupRoute
'/(logistics)/logistics/deliverySchedule': typeof logisticsLogisticsDeliveryScheduleRoute
'/_adminLayout/admin/servers': typeof AdminLayoutAdminServersRoute
'/_adminLayout/admin/settings': typeof AdminLayoutAdminSettingsRoute
'/(auth)/user/': typeof authUserIndexRoute
'/(mobileStuff)/_mobileLayout/m/cyclecounts': typeof mobileStuffMobileLayoutMCyclecountsRoute
'/(mobileStuff)/_mobileLayout/m/delivery': typeof mobileStuffMobileLayoutMDeliveryRoute
'/(mobileStuff)/_mobileLayout/m/relocate': typeof mobileStuffMobileLayoutMRelocateRoute
@@ -187,11 +205,13 @@ export interface FileRouteTypes {
| '/'
| '/login'
| '/admin'
| '/user/profile'
| '/user/resetpassword'
| '/user/signup'
| '/logistics/deliverySchedule'
| '/admin/servers'
| '/admin/settings'
| '/user'
| '/m/cyclecounts'
| '/m/delivery'
| '/m/relocate'
@@ -203,11 +223,13 @@ export interface FileRouteTypes {
| '/'
| '/login'
| '/admin'
| '/user/profile'
| '/user/resetpassword'
| '/user/signup'
| '/logistics/deliverySchedule'
| '/admin/servers'
| '/admin/settings'
| '/user'
| '/m/cyclecounts'
| '/m/delivery'
| '/m/relocate'
@@ -223,11 +245,13 @@ export interface FileRouteTypes {
| '/(auth)/login'
| '/_adminLayout/admin'
| '/_adminLayout/admin/_users'
| '/(auth)/user/profile'
| '/(auth)/user/resetpassword'
| '/(auth)/user/signup'
| '/(logistics)/logistics/deliverySchedule'
| '/_adminLayout/admin/servers'
| '/_adminLayout/admin/settings'
| '/(auth)/user/'
| '/(mobileStuff)/_mobileLayout/m/cyclecounts'
| '/(mobileStuff)/_mobileLayout/m/delivery'
| '/(mobileStuff)/_mobileLayout/m/relocate'
@@ -241,9 +265,11 @@ export interface RootRouteChildren {
AdminLayoutRouteRoute: typeof AdminLayoutRouteRouteWithChildren
mobileStuffRoute: typeof mobileStuffRouteWithChildren
authLoginRoute: typeof authLoginRoute
authUserProfileRoute: typeof authUserProfileRoute
authUserResetpasswordRoute: typeof authUserResetpasswordRoute
authUserSignupRoute: typeof authUserSignupRoute
logisticsLogisticsDeliveryScheduleRoute: typeof logisticsLogisticsDeliveryScheduleRoute
authUserIndexRoute: typeof authUserIndexRoute
}
declare module '@tanstack/react-router' {
@@ -290,6 +316,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof mobileStuffMobileLayoutRouteRouteImport
parentRoute: typeof mobileStuffRoute
}
'/(auth)/user/': {
id: '/(auth)/user/'
path: '/user'
fullPath: '/user'
preLoaderRoute: typeof authUserIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/_adminLayout/admin/settings': {
id: '/_adminLayout/admin/settings'
path: '/settings'
@@ -325,6 +358,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof authUserResetpasswordRouteImport
parentRoute: typeof rootRouteImport
}
'/(auth)/user/profile': {
id: '/(auth)/user/profile'
path: '/user/profile'
fullPath: '/user/profile'
preLoaderRoute: typeof authUserProfileRouteImport
parentRoute: typeof rootRouteImport
}
'/_adminLayout/admin/_users': {
id: '/_adminLayout/admin/_users'
path: '/admin'
@@ -460,10 +500,12 @@ const rootRouteChildren: RootRouteChildren = {
AdminLayoutRouteRoute: AdminLayoutRouteRouteWithChildren,
mobileStuffRoute: mobileStuffRouteWithChildren,
authLoginRoute: authLoginRoute,
authUserProfileRoute: authUserProfileRoute,
authUserResetpasswordRoute: authUserResetpasswordRoute,
authUserSignupRoute: authUserSignupRoute,
logisticsLogisticsDeliveryScheduleRoute:
logisticsLogisticsDeliveryScheduleRoute,
authUserIndexRoute: authUserIndexRoute,
}
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)

View File

@@ -1,133 +1,129 @@
import { Link, useRouter, useSearch } from "@tanstack/react-router";
import {
getSession,
signin,
useAuth,
useUserRoles,
} from "../../../lib/authClient";
import { useAppForm } from "../../../lib/formStuff";
import { LstCard } from "../../../components/ui/lstCard";
import axios from "axios";
import { toast } from "sonner";
import {
CardContent,
CardDescription,
CardHeader,
CardTitle,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "../../../components/ui/card";
import { LstCard } from "../../../components/ui/lstCard";
import { getSession, useAuth, useUserRoles } from "../../../lib/authClient";
import { useAppForm } from "../../../lib/formStuff";
export default function LoginForm() {
const router = useRouter();
const search = useSearch({ from: "/(auth)/login" });
const username = localStorage.getItem("username") || "";
const rememeberMe = localStorage.getItem("rememberMe") === "true";
const { setSession } = useAuth();
const { fetchRoles } = useUserRoles();
const router = useRouter();
const search = useSearch({ from: "/(auth)/login" });
const username = localStorage.getItem("username") || "";
const rememberMe = localStorage.getItem("rememberMe") === "true";
const { setSession } = useAuth();
const { fetchRoles } = useUserRoles();
const form = useAppForm({
defaultValues: {
username: username,
password: "",
rememberMe: rememeberMe,
},
onSubmit: async ({ value }) => {
if (value.rememberMe) {
localStorage.setItem("rememberMe", value.rememberMe.toString());
localStorage.setItem("username", value.username);
} else {
localStorage.removeItem("rememberMe");
localStorage.removeItem("username");
}
const form = useAppForm({
defaultValues: {
username: username,
password: "",
rememberMe: rememberMe,
},
onSubmit: async ({ value }) => {
if (value.rememberMe) {
localStorage.setItem("rememberMe", value.rememberMe.toString());
localStorage.setItem("username", value.username);
} else {
localStorage.removeItem("rememberMe");
localStorage.removeItem("username");
}
try {
await signin({
username: value.username,
password: value.password,
});
try {
await axios.post("/lst/api/user/login", {
username: value.username,
password: value.password,
});
const session = await getSession();
setSession(session);
form.reset();
fetchRoles();
const session = await getSession();
setSession(session);
form.reset();
fetchRoles();
toast.success(
`Welcome back ${session?.user.name ? session?.user.name : session?.user.username} `
);
router.invalidate();
router.history.push(search.redirect ? search.redirect : "/");
} catch (error) {
// @ts-ignore
toast.error(error?.message);
}
},
});
return (
<div className="">
<LstCard className="p-3 w-96">
<CardHeader>
<CardTitle>Login to your account</CardTitle>
<CardDescription>
Enter your username and password below
</CardDescription>
</CardHeader>
<CardContent>
<form
onSubmit={(e) => {
e.preventDefault();
form.handleSubmit();
}}
>
<form.AppField
name="username"
children={(field) => (
<field.InputField
label="Username"
inputType="string"
required={true}
/>
)}
/>
<form.AppField
name="password"
children={(field) => (
<field.InputPasswordField
label="Password"
required={true}
/>
)}
/>
<div className="flex flex-row justify-between mt-3 mb-3">
<form.AppField
name="rememberMe"
children={(field) => (
<field.CheckboxField label="Remember me" />
)}
/>
<Link
to="/user/resetpassword"
className="inline-block text-sm underline-offset-4 hover:underline"
>
Forgot your password?
</Link>
</div>
toast.success(
`Welcome back ${session?.user.name ? session?.user.name : session?.user.username} `,
);
router.invalidate();
router.history.push(search.redirect ? search.redirect : "/");
} catch (error) {
// @ts-ignore
if (!error.response.success) {
// @ts-ignore
toast.error(error.response.data.message);
} else {
// @ts-ignore
toast.error(error?.message);
}
}
},
});
return (
<div className="">
<LstCard className="p-3 w-96">
<CardHeader>
<CardTitle>Login to your account</CardTitle>
<CardDescription>
Enter your username and password below
</CardDescription>
</CardHeader>
<CardContent>
<form
onSubmit={(e) => {
e.preventDefault();
form.handleSubmit();
}}
>
<form.AppField
name="username"
children={(field) => (
<field.InputField
label="Username"
inputType="string"
required={true}
/>
)}
/>
<form.AppField
name="password"
children={(field) => (
<field.InputPasswordField label="Password" required={true} />
)}
/>
<div className="flex flex-row justify-between mt-3 mb-3">
<form.AppField
name="rememberMe"
children={(field) => (
<field.CheckboxField label="Remember me" />
)}
/>
<Link
to="/user/resetpassword"
className="inline-block text-sm underline-offset-4 hover:underline"
>
Forgot your password?
</Link>
</div>
<div className="flex justify-end mt-2">
<form.AppForm>
<form.SubmitButton>Login</form.SubmitButton>
</form.AppForm>
</div>
</form>
<div className="flex justify-end mt-2">
<form.AppForm>
<form.SubmitButton>Login</form.SubmitButton>
</form.AppForm>
</div>
</form>
<div className="mt-4 text-center text-sm">
Don&apos;t have an account?{" "}
<Link
to={"/user/signup"}
className="underline underline-offset-4"
>
Sign up
</Link>
</div>
</CardContent>
</LstCard>
</div>
);
<div className="mt-4 text-center text-sm">
Don&apos;t have an account?{" "}
<Link to={"/user/signup"} className="underline underline-offset-4">
Sign up
</Link>
</div>
</CardContent>
</LstCard>
</div>
);
}

View File

@@ -0,0 +1,13 @@
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/(auth)/user/")({
component: RouteComponent,
});
function RouteComponent() {
return (
<div>
<span>Nothing here </span>
</div>
);
}

View File

@@ -0,0 +1,40 @@
import { createFileRoute, redirect } from "@tanstack/react-router";
import { authClient, useAuth } from "../../../lib/authClient";
export const Route = createFileRoute("/(auth)/user/profile")({
beforeLoad: async () => {
const result = await authClient.getSession({
query: { disableCookieCache: true }, // force DB/Server lookup
});
//console.log("session check:", result.data);
if (!result.data) {
throw redirect({
to: "/login",
search: {
redirect: location.pathname + location.search,
},
});
}
},
component: RouteComponent,
});
function RouteComponent() {
const { session } = useAuth();
return (
<div className="m-2">
<div>
<span>Things you can change</span>
<ol>
<li>Display name: {session?.user.displayUsername}</li>
<li>Name: {session?.user.name}</li>
<li>Image: To be added</li>
<li>password: **************</li>
</ol>
</div>
</div>
);
}

View File

@@ -1,66 +1,62 @@
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import { tanstackRouter } from "@tanstack/router-plugin/vite";
import tailwindcss from "@tailwindcss/vite";
import path from "path";
import { tanstackRouter } from "@tanstack/router-plugin/vite";
import react from "@vitejs/plugin-react-swc";
import dotenv from "dotenv";
import path from "path";
import { fileURLToPath } from "url";
import { defineConfig } from "vite";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
dotenv.config({
path: path.resolve(__dirname, "../.env"),
path: path.resolve(__dirname, "../.env"),
});
// https://vite.dev/config/
export default defineConfig({
plugins: [
react(),
tailwindcss(),
tanstackRouter({
target: "react",
autoCodeSplitting: true,
}),
],
base: "/lst/app",
build: {
//outDir: "../backend/frontend",
//assetsDir: "assets",
emptyOutDir: true,
},
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
server: {
port: 5500,
host: true,
allowedHosts: true,
proxy: {
"/lst/api": {
target: `http://localhost:${Number(
process.env.VITE_PORT || 4000
)}`,
changeOrigin: true,
secure: false,
},
"/lst/ws": {
target: `ws://localhost:${Number(
process.env.VITE_PORT || 4000
)}`, // Your Go WebSocket endpoint
ws: true,
changeOrigin: true,
secure: false,
rewrite: (path) => path.replace(/^\/ws/, ""),
},
// Proxy docs to Docusaurus
"/lst/d": {
target: `http://localhost:4300`,
changeOrigin: true,
//rewrite: (path) => path.replace(/^\/lst\/d/, "/"),
},
},
},
plugins: [
react(),
tailwindcss(),
tanstackRouter({
target: "react",
autoCodeSplitting: true,
}),
],
base: "/lst/app",
build: {
//outDir: "../backend/frontend",
//assetsDir: "assets",
emptyOutDir: true,
},
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
server: {
port: 5500,
host: true,
allowedHosts: true,
proxy: {
"/lst/api": {
target: `http://localhost:${Number(process.env.VITE_PORT || 4000)}`,
changeOrigin: true,
secure: false,
},
"/lst/ws": {
target: `ws://localhost:${Number(process.env.VITE_PORT || 4000)}`, // Your Go WebSocket endpoint
ws: true,
changeOrigin: true,
secure: false,
rewrite: (path) => path.replace(/^\/ws/, ""),
},
// Proxy docs to Docusaurus
"/lst/d": {
target: `http://localhost:4300`,
changeOrigin: true,
//rewrite: (path) => path.replace(/^\/lst\/d/, "/"),
},
},
},
});

File diff suppressed because it is too large Load Diff

View File

@@ -34,6 +34,7 @@
"@tanstack/react-query": "^5.81.2",
"@tanstack/react-router": "^1.121.34",
"@tanstack/react-table": "^8.21.3",
"better-auth": "^1.3.28",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",

View File

@@ -1,151 +1,147 @@
import {
ColumnDef,
flexRender,
getCoreRowModel,
useReactTable,
getPaginationRowModel,
getSortedRowModel,
ColumnDef,
flexRender,
getCoreRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
//import { Button } from "@/components/ui/button";
import { useState } from "react";
import { ScrollArea } from "@/components/ui/scroll-area";
import { LstCard } from "@/components/extendedUI/LstCard";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
info: any;
columns: ColumnDef<TData, TValue>[];
data: TData[];
info: any;
}
type ColumnSort = {
id: string;
desc: boolean;
id: string;
desc: boolean;
};
type SortingState = ColumnSort[];
export function InvTable<TData, TValue>({
columns,
data,
info,
columns,
data,
info,
}: DataTableProps<TData, TValue>) {
const [sorting, setSorting] = useState<SortingState>([]);
const [pagination, setPagination] = useState({
pageIndex: 0, //initial page index
pageSize: 500, //default page size
});
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onPaginationChange: setPagination,
getSortedRowModel: getSortedRowModel(),
state: {
//...
pagination,
sorting,
},
manualSorting: true,
onSortingChange: setSorting,
initialState: {
sorting: [
{
id: "DaysSinceLast",
desc: true,
},
],
},
});
//console.log(table.getState().sorting);
//console.log(parseInt(style.height.replace("px", "")) - 50);
console.log(info);
return (
<LstCard
className="p-3"
// style={{
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
// height: `${parseInt(style.height.replace("px", "")) - 150}px`,
// cursor: "move",
// }}
//style={{ overflow: "auto" }}
>
<div>
<div className="flex flex-row justify-between">
<p className="text-center text-pretty">
{info.rowType} {data.length > 0 ? "lanes" : "lane"}{" "}
older than: {info.age}, {data.length} needing to be
completed
</p>
</div>
<ScrollArea className="h-72 rounded-md border m-2">
<Table
// style={{
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
// height: `${parseInt(style.height.replace("px", "")) - 200}px`,
// cursor: "move",
// }}
>
<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?.length ? (
table.getRowModel().rows.map((row) => (
<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>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</ScrollArea>
</div>
{/* <div className="flex items-center justify-end space-x-2">
const [sorting, setSorting] = useState<SortingState>([]);
const [pagination, setPagination] = useState({
pageIndex: 0, //initial page index
pageSize: 500, //default page size
});
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
onPaginationChange: setPagination,
getSortedRowModel: getSortedRowModel(),
state: {
//...
pagination,
sorting,
},
manualSorting: true,
onSortingChange: setSorting,
initialState: {
sorting: [
{
id: "DaysSinceLast",
desc: true,
},
],
},
});
//console.log(table.getState().sorting);
//console.log(parseInt(style.height.replace("px", "")) - 50);
// console.log(info);
return (
<LstCard
className="p-3"
// style={{
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
// height: `${parseInt(style.height.replace("px", "")) - 150}px`,
// cursor: "move",
// }}
//style={{ overflow: "auto" }}
>
<div>
<div className="flex flex-row justify-between">
<p className="text-center text-pretty">
{info.rowType} {data.length > 0 ? "lanes" : "lane"} older than:{" "}
{info.age}, {data.length} needing to be completed
</p>
</div>
<ScrollArea className="h-72 rounded-md border m-2">
<Table
// style={{
// width: `${parseInt(style.width.replace("px", "")) - 50}px`,
// height: `${parseInt(style.height.replace("px", "")) - 200}px`,
// cursor: "move",
// }}
>
<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?.length ? (
table.getRowModel().rows.map((row) => (
<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>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</ScrollArea>
</div>
{/* <div className="flex items-center justify-end space-x-2">
<Button
variant="outline"
size="sm"
@@ -163,6 +159,6 @@ export function InvTable<TData, TValue>({
Next
</Button>
</div> */}
</LstCard>
);
</LstCard>
);
}

17418
lstV2/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -68,6 +68,7 @@
"adm-zip": "^0.5.16",
"axios": "^1.10.0",
"bcryptjs": "^3.0.2",
"better-auth": "^1.3.28",
"croner": "^9.1.0",
"date-fns": "^4.1.0",
"date-fns-tz": "^3.2.0",

34
scripts/lstAppMoves.mjs Normal file
View File

@@ -0,0 +1,34 @@
import fs from "fs";
import path from "path";
const src_views = path.resolve("app/src/pkg/utils/mail/views");
const dest_views = path.resolve("dist/src/pkg/utils/mail/views");
const src_settings = path.resolve(
"app/src/internal/system/controller/settings/settings.json",
);
const dest_settings = path.resolve(
"dist/src/internal/system/controller/settings/settings.json",
);
// Delete old views if they exist
if (fs.existsSync(dest_views)) {
fs.rmSync(dest_views, { recursive: true, force: true });
}
// Delete old settings file if it exists
if (fs.existsSync(dest_settings)) {
fs.rmSync(dest_settings, { force: true }); // for single files we dont need the recursive
}
// Ensure the destination directory exists for settings.json
const dest_settings_dir = path.dirname(dest_settings);
if (!fs.existsSync(dest_settings_dir)) {
fs.mkdirSync(dest_settings_dir, { recursive: true });
}
// Copy files
fs.copyFileSync(src_settings, dest_settings);
fs.cpSync(src_views, dest_views, { recursive: true });
console.log(`All files copied`);