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 { 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 { settings {
encodeUrl: true encodeUrl: true
timeout: 0
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,8 +1,9 @@
vars { vars {
url: http://localhost:5500 url: http://localhost:5500
session_cookie: session_cookie:
urlv2: http://usmcd1vms036:3000 urlv2: http://localhost:3000
jwtV2: jwtV2:
userID:
} }
vars:secret [ vars:secret [
v2Password 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> </DropdownMenuLabel>
<DropdownMenuSeparator /> <DropdownMenuSeparator />
<DropdownMenuItem> <DropdownMenuItem>
{/* <Link to="/passwordChange"> <Link to="/user/profile">Profile</Link>
Password Change
</Link> */}
</DropdownMenuItem> </DropdownMenuItem>
{/* <DropdownMenuItem>Billing</DropdownMenuItem> {/* <DropdownMenuItem>Billing</DropdownMenuItem>
<DropdownMenuItem>Team</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 IndexRouteImport } from './routes/index'
import { Route as authLoginRouteImport } from './routes/(auth)/login' import { Route as authLoginRouteImport } from './routes/(auth)/login'
import { Route as mobileStuffMobileLayoutRouteRouteImport } from './routes/(mobileStuff)/_mobileLayout/route' 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 AdminLayoutAdminSettingsRouteImport } from './routes/_adminLayout/admin/settings'
import { Route as AdminLayoutAdminServersRouteImport } from './routes/_adminLayout/admin/servers' import { Route as AdminLayoutAdminServersRouteImport } from './routes/_adminLayout/admin/servers'
import { Route as logisticsLogisticsDeliveryScheduleRouteImport } from './routes/(logistics)/logistics/deliverySchedule' import { Route as logisticsLogisticsDeliveryScheduleRouteImport } from './routes/(logistics)/logistics/deliverySchedule'
import { Route as authUserSignupRouteImport } from './routes/(auth)/user/signup' import { Route as authUserSignupRouteImport } from './routes/(auth)/user/signup'
import { Route as authUserResetpasswordRouteImport } from './routes/(auth)/user/resetpassword' 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 AdminLayoutAdminUsersRouteRouteImport } from './routes/_adminLayout/admin/_users/route'
import { Route as mobileStuffMobileLayoutMIndexRouteImport } from './routes/(mobileStuff)/_mobileLayout/m/index' import { Route as mobileStuffMobileLayoutMIndexRouteImport } from './routes/(mobileStuff)/_mobileLayout/m/index'
import { Route as AdminLayoutAdminUsersUsersRouteImport } from './routes/_adminLayout/admin/_users/users' import { Route as AdminLayoutAdminUsersUsersRouteImport } from './routes/_adminLayout/admin/_users/users'
@@ -59,6 +61,11 @@ const mobileStuffMobileLayoutRouteRoute =
id: '/_mobileLayout', id: '/_mobileLayout',
getParentRoute: () => mobileStuffRoute, getParentRoute: () => mobileStuffRoute,
} as any) } as any)
const authUserIndexRoute = authUserIndexRouteImport.update({
id: '/(auth)/user/',
path: '/user/',
getParentRoute: () => rootRouteImport,
} as any)
const AdminLayoutAdminSettingsRoute = const AdminLayoutAdminSettingsRoute =
AdminLayoutAdminSettingsRouteImport.update({ AdminLayoutAdminSettingsRouteImport.update({
id: '/settings', id: '/settings',
@@ -86,6 +93,11 @@ const authUserResetpasswordRoute = authUserResetpasswordRouteImport.update({
path: '/user/resetpassword', path: '/user/resetpassword',
getParentRoute: () => rootRouteImport, getParentRoute: () => rootRouteImport,
} as any) } as any)
const authUserProfileRoute = authUserProfileRouteImport.update({
id: '/(auth)/user/profile',
path: '/user/profile',
getParentRoute: () => rootRouteImport,
} as any)
const AdminLayoutAdminUsersRouteRoute = const AdminLayoutAdminUsersRouteRoute =
AdminLayoutAdminUsersRouteRouteImport.update({ AdminLayoutAdminUsersRouteRouteImport.update({
id: '/_users', id: '/_users',
@@ -132,11 +144,13 @@ export interface FileRoutesByFullPath {
'/': typeof mobileStuffMobileLayoutRouteRouteWithChildren '/': typeof mobileStuffMobileLayoutRouteRouteWithChildren
'/login': typeof authLoginRoute '/login': typeof authLoginRoute
'/admin': typeof AdminLayoutAdminUsersRouteRouteWithChildren '/admin': typeof AdminLayoutAdminUsersRouteRouteWithChildren
'/user/profile': typeof authUserProfileRoute
'/user/resetpassword': typeof authUserResetpasswordRoute '/user/resetpassword': typeof authUserResetpasswordRoute
'/user/signup': typeof authUserSignupRoute '/user/signup': typeof authUserSignupRoute
'/logistics/deliverySchedule': typeof logisticsLogisticsDeliveryScheduleRoute '/logistics/deliverySchedule': typeof logisticsLogisticsDeliveryScheduleRoute
'/admin/servers': typeof AdminLayoutAdminServersRoute '/admin/servers': typeof AdminLayoutAdminServersRoute
'/admin/settings': typeof AdminLayoutAdminSettingsRoute '/admin/settings': typeof AdminLayoutAdminSettingsRoute
'/user': typeof authUserIndexRoute
'/m/cyclecounts': typeof mobileStuffMobileLayoutMCyclecountsRoute '/m/cyclecounts': typeof mobileStuffMobileLayoutMCyclecountsRoute
'/m/delivery': typeof mobileStuffMobileLayoutMDeliveryRoute '/m/delivery': typeof mobileStuffMobileLayoutMDeliveryRoute
'/m/relocate': typeof mobileStuffMobileLayoutMRelocateRoute '/m/relocate': typeof mobileStuffMobileLayoutMRelocateRoute
@@ -148,11 +162,13 @@ export interface FileRoutesByTo {
'/': typeof mobileStuffMobileLayoutRouteRouteWithChildren '/': typeof mobileStuffMobileLayoutRouteRouteWithChildren
'/login': typeof authLoginRoute '/login': typeof authLoginRoute
'/admin': typeof AdminLayoutAdminUsersRouteRouteWithChildren '/admin': typeof AdminLayoutAdminUsersRouteRouteWithChildren
'/user/profile': typeof authUserProfileRoute
'/user/resetpassword': typeof authUserResetpasswordRoute '/user/resetpassword': typeof authUserResetpasswordRoute
'/user/signup': typeof authUserSignupRoute '/user/signup': typeof authUserSignupRoute
'/logistics/deliverySchedule': typeof logisticsLogisticsDeliveryScheduleRoute '/logistics/deliverySchedule': typeof logisticsLogisticsDeliveryScheduleRoute
'/admin/servers': typeof AdminLayoutAdminServersRoute '/admin/servers': typeof AdminLayoutAdminServersRoute
'/admin/settings': typeof AdminLayoutAdminSettingsRoute '/admin/settings': typeof AdminLayoutAdminSettingsRoute
'/user': typeof authUserIndexRoute
'/m/cyclecounts': typeof mobileStuffMobileLayoutMCyclecountsRoute '/m/cyclecounts': typeof mobileStuffMobileLayoutMCyclecountsRoute
'/m/delivery': typeof mobileStuffMobileLayoutMDeliveryRoute '/m/delivery': typeof mobileStuffMobileLayoutMDeliveryRoute
'/m/relocate': typeof mobileStuffMobileLayoutMRelocateRoute '/m/relocate': typeof mobileStuffMobileLayoutMRelocateRoute
@@ -169,11 +185,13 @@ export interface FileRoutesById {
'/(auth)/login': typeof authLoginRoute '/(auth)/login': typeof authLoginRoute
'/_adminLayout/admin': typeof AdminLayoutAdminRouteWithChildren '/_adminLayout/admin': typeof AdminLayoutAdminRouteWithChildren
'/_adminLayout/admin/_users': typeof AdminLayoutAdminUsersRouteRouteWithChildren '/_adminLayout/admin/_users': typeof AdminLayoutAdminUsersRouteRouteWithChildren
'/(auth)/user/profile': typeof authUserProfileRoute
'/(auth)/user/resetpassword': typeof authUserResetpasswordRoute '/(auth)/user/resetpassword': typeof authUserResetpasswordRoute
'/(auth)/user/signup': typeof authUserSignupRoute '/(auth)/user/signup': typeof authUserSignupRoute
'/(logistics)/logistics/deliverySchedule': typeof logisticsLogisticsDeliveryScheduleRoute '/(logistics)/logistics/deliverySchedule': typeof logisticsLogisticsDeliveryScheduleRoute
'/_adminLayout/admin/servers': typeof AdminLayoutAdminServersRoute '/_adminLayout/admin/servers': typeof AdminLayoutAdminServersRoute
'/_adminLayout/admin/settings': typeof AdminLayoutAdminSettingsRoute '/_adminLayout/admin/settings': typeof AdminLayoutAdminSettingsRoute
'/(auth)/user/': typeof authUserIndexRoute
'/(mobileStuff)/_mobileLayout/m/cyclecounts': typeof mobileStuffMobileLayoutMCyclecountsRoute '/(mobileStuff)/_mobileLayout/m/cyclecounts': typeof mobileStuffMobileLayoutMCyclecountsRoute
'/(mobileStuff)/_mobileLayout/m/delivery': typeof mobileStuffMobileLayoutMDeliveryRoute '/(mobileStuff)/_mobileLayout/m/delivery': typeof mobileStuffMobileLayoutMDeliveryRoute
'/(mobileStuff)/_mobileLayout/m/relocate': typeof mobileStuffMobileLayoutMRelocateRoute '/(mobileStuff)/_mobileLayout/m/relocate': typeof mobileStuffMobileLayoutMRelocateRoute
@@ -187,11 +205,13 @@ export interface FileRouteTypes {
| '/' | '/'
| '/login' | '/login'
| '/admin' | '/admin'
| '/user/profile'
| '/user/resetpassword' | '/user/resetpassword'
| '/user/signup' | '/user/signup'
| '/logistics/deliverySchedule' | '/logistics/deliverySchedule'
| '/admin/servers' | '/admin/servers'
| '/admin/settings' | '/admin/settings'
| '/user'
| '/m/cyclecounts' | '/m/cyclecounts'
| '/m/delivery' | '/m/delivery'
| '/m/relocate' | '/m/relocate'
@@ -203,11 +223,13 @@ export interface FileRouteTypes {
| '/' | '/'
| '/login' | '/login'
| '/admin' | '/admin'
| '/user/profile'
| '/user/resetpassword' | '/user/resetpassword'
| '/user/signup' | '/user/signup'
| '/logistics/deliverySchedule' | '/logistics/deliverySchedule'
| '/admin/servers' | '/admin/servers'
| '/admin/settings' | '/admin/settings'
| '/user'
| '/m/cyclecounts' | '/m/cyclecounts'
| '/m/delivery' | '/m/delivery'
| '/m/relocate' | '/m/relocate'
@@ -223,11 +245,13 @@ export interface FileRouteTypes {
| '/(auth)/login' | '/(auth)/login'
| '/_adminLayout/admin' | '/_adminLayout/admin'
| '/_adminLayout/admin/_users' | '/_adminLayout/admin/_users'
| '/(auth)/user/profile'
| '/(auth)/user/resetpassword' | '/(auth)/user/resetpassword'
| '/(auth)/user/signup' | '/(auth)/user/signup'
| '/(logistics)/logistics/deliverySchedule' | '/(logistics)/logistics/deliverySchedule'
| '/_adminLayout/admin/servers' | '/_adminLayout/admin/servers'
| '/_adminLayout/admin/settings' | '/_adminLayout/admin/settings'
| '/(auth)/user/'
| '/(mobileStuff)/_mobileLayout/m/cyclecounts' | '/(mobileStuff)/_mobileLayout/m/cyclecounts'
| '/(mobileStuff)/_mobileLayout/m/delivery' | '/(mobileStuff)/_mobileLayout/m/delivery'
| '/(mobileStuff)/_mobileLayout/m/relocate' | '/(mobileStuff)/_mobileLayout/m/relocate'
@@ -241,9 +265,11 @@ export interface RootRouteChildren {
AdminLayoutRouteRoute: typeof AdminLayoutRouteRouteWithChildren AdminLayoutRouteRoute: typeof AdminLayoutRouteRouteWithChildren
mobileStuffRoute: typeof mobileStuffRouteWithChildren mobileStuffRoute: typeof mobileStuffRouteWithChildren
authLoginRoute: typeof authLoginRoute authLoginRoute: typeof authLoginRoute
authUserProfileRoute: typeof authUserProfileRoute
authUserResetpasswordRoute: typeof authUserResetpasswordRoute authUserResetpasswordRoute: typeof authUserResetpasswordRoute
authUserSignupRoute: typeof authUserSignupRoute authUserSignupRoute: typeof authUserSignupRoute
logisticsLogisticsDeliveryScheduleRoute: typeof logisticsLogisticsDeliveryScheduleRoute logisticsLogisticsDeliveryScheduleRoute: typeof logisticsLogisticsDeliveryScheduleRoute
authUserIndexRoute: typeof authUserIndexRoute
} }
declare module '@tanstack/react-router' { declare module '@tanstack/react-router' {
@@ -290,6 +316,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof mobileStuffMobileLayoutRouteRouteImport preLoaderRoute: typeof mobileStuffMobileLayoutRouteRouteImport
parentRoute: typeof mobileStuffRoute parentRoute: typeof mobileStuffRoute
} }
'/(auth)/user/': {
id: '/(auth)/user/'
path: '/user'
fullPath: '/user'
preLoaderRoute: typeof authUserIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/_adminLayout/admin/settings': { '/_adminLayout/admin/settings': {
id: '/_adminLayout/admin/settings' id: '/_adminLayout/admin/settings'
path: '/settings' path: '/settings'
@@ -325,6 +358,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof authUserResetpasswordRouteImport preLoaderRoute: typeof authUserResetpasswordRouteImport
parentRoute: typeof rootRouteImport 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': { '/_adminLayout/admin/_users': {
id: '/_adminLayout/admin/_users' id: '/_adminLayout/admin/_users'
path: '/admin' path: '/admin'
@@ -460,10 +500,12 @@ const rootRouteChildren: RootRouteChildren = {
AdminLayoutRouteRoute: AdminLayoutRouteRouteWithChildren, AdminLayoutRouteRoute: AdminLayoutRouteRouteWithChildren,
mobileStuffRoute: mobileStuffRouteWithChildren, mobileStuffRoute: mobileStuffRouteWithChildren,
authLoginRoute: authLoginRoute, authLoginRoute: authLoginRoute,
authUserProfileRoute: authUserProfileRoute,
authUserResetpasswordRoute: authUserResetpasswordRoute, authUserResetpasswordRoute: authUserResetpasswordRoute,
authUserSignupRoute: authUserSignupRoute, authUserSignupRoute: authUserSignupRoute,
logisticsLogisticsDeliveryScheduleRoute: logisticsLogisticsDeliveryScheduleRoute:
logisticsLogisticsDeliveryScheduleRoute, logisticsLogisticsDeliveryScheduleRoute,
authUserIndexRoute: authUserIndexRoute,
} }
export const routeTree = rootRouteImport export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren) ._addFileChildren(rootRouteChildren)

View File

@@ -1,133 +1,129 @@
import { Link, useRouter, useSearch } from "@tanstack/react-router"; import { Link, useRouter, useSearch } from "@tanstack/react-router";
import { import axios from "axios";
getSession,
signin,
useAuth,
useUserRoles,
} from "../../../lib/authClient";
import { useAppForm } from "../../../lib/formStuff";
import { LstCard } from "../../../components/ui/lstCard";
import { toast } from "sonner"; import { toast } from "sonner";
import { import {
CardContent, CardContent,
CardDescription, CardDescription,
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "../../../components/ui/card"; } 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() { export default function LoginForm() {
const router = useRouter(); const router = useRouter();
const search = useSearch({ from: "/(auth)/login" }); const search = useSearch({ from: "/(auth)/login" });
const username = localStorage.getItem("username") || ""; const username = localStorage.getItem("username") || "";
const rememeberMe = localStorage.getItem("rememberMe") === "true"; const rememberMe = localStorage.getItem("rememberMe") === "true";
const { setSession } = useAuth(); const { setSession } = useAuth();
const { fetchRoles } = useUserRoles(); const { fetchRoles } = useUserRoles();
const form = useAppForm({ const form = useAppForm({
defaultValues: { defaultValues: {
username: username, username: username,
password: "", password: "",
rememberMe: rememeberMe, rememberMe: rememberMe,
}, },
onSubmit: async ({ value }) => { onSubmit: async ({ value }) => {
if (value.rememberMe) { if (value.rememberMe) {
localStorage.setItem("rememberMe", value.rememberMe.toString()); localStorage.setItem("rememberMe", value.rememberMe.toString());
localStorage.setItem("username", value.username); localStorage.setItem("username", value.username);
} else { } else {
localStorage.removeItem("rememberMe"); localStorage.removeItem("rememberMe");
localStorage.removeItem("username"); localStorage.removeItem("username");
} }
try { try {
await signin({ await axios.post("/lst/api/user/login", {
username: value.username, username: value.username,
password: value.password, password: value.password,
}); });
const session = await getSession(); const session = await getSession();
setSession(session); setSession(session);
form.reset(); form.reset();
fetchRoles(); fetchRoles();
toast.success( toast.success(
`Welcome back ${session?.user.name ? session?.user.name : session?.user.username} ` `Welcome back ${session?.user.name ? session?.user.name : session?.user.username} `,
); );
router.invalidate(); router.invalidate();
router.history.push(search.redirect ? search.redirect : "/"); router.history.push(search.redirect ? search.redirect : "/");
} catch (error) { } catch (error) {
// @ts-ignore // @ts-ignore
toast.error(error?.message); if (!error.response.success) {
} // @ts-ignore
}, toast.error(error.response.data.message);
}); } else {
return ( // @ts-ignore
<div className=""> toast.error(error?.message);
<LstCard className="p-3 w-96"> }
<CardHeader> }
<CardTitle>Login to your account</CardTitle> },
<CardDescription> });
Enter your username and password below return (
</CardDescription> <div className="">
</CardHeader> <LstCard className="p-3 w-96">
<CardContent> <CardHeader>
<form <CardTitle>Login to your account</CardTitle>
onSubmit={(e) => { <CardDescription>
e.preventDefault(); Enter your username and password below
form.handleSubmit(); </CardDescription>
}} </CardHeader>
> <CardContent>
<form.AppField <form
name="username" onSubmit={(e) => {
children={(field) => ( e.preventDefault();
<field.InputField form.handleSubmit();
label="Username" }}
inputType="string" >
required={true} <form.AppField
/> name="username"
)} children={(field) => (
/> <field.InputField
<form.AppField label="Username"
name="password" inputType="string"
children={(field) => ( required={true}
<field.InputPasswordField />
label="Password" )}
required={true} />
/> <form.AppField
)} name="password"
/> children={(field) => (
<div className="flex flex-row justify-between mt-3 mb-3"> <field.InputPasswordField label="Password" required={true} />
<form.AppField )}
name="rememberMe" />
children={(field) => ( <div className="flex flex-row justify-between mt-3 mb-3">
<field.CheckboxField label="Remember me" /> <form.AppField
)} name="rememberMe"
/> children={(field) => (
<Link <field.CheckboxField label="Remember me" />
to="/user/resetpassword" )}
className="inline-block text-sm underline-offset-4 hover:underline" />
> <Link
Forgot your password? to="/user/resetpassword"
</Link> className="inline-block text-sm underline-offset-4 hover:underline"
</div> >
Forgot your password?
</Link>
</div>
<div className="flex justify-end mt-2"> <div className="flex justify-end mt-2">
<form.AppForm> <form.AppForm>
<form.SubmitButton>Login</form.SubmitButton> <form.SubmitButton>Login</form.SubmitButton>
</form.AppForm> </form.AppForm>
</div> </div>
</form> </form>
<div className="mt-4 text-center text-sm"> <div className="mt-4 text-center text-sm">
Don&apos;t have an account?{" "} Don&apos;t have an account?{" "}
<Link <Link to={"/user/signup"} className="underline underline-offset-4">
to={"/user/signup"} Sign up
className="underline underline-offset-4" </Link>
> </div>
Sign up </CardContent>
</Link> </LstCard>
</div> </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 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 dotenv from "dotenv";
import path from "path";
import { fileURLToPath } from "url"; import { fileURLToPath } from "url";
import { defineConfig } from "vite";
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename); const __dirname = path.dirname(__filename);
dotenv.config({ dotenv.config({
path: path.resolve(__dirname, "../.env"), path: path.resolve(__dirname, "../.env"),
}); });
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
react(), react(),
tailwindcss(), tailwindcss(),
tanstackRouter({ tanstackRouter({
target: "react", target: "react",
autoCodeSplitting: true, autoCodeSplitting: true,
}), }),
], ],
base: "/lst/app", base: "/lst/app",
build: { build: {
//outDir: "../backend/frontend", //outDir: "../backend/frontend",
//assetsDir: "assets", //assetsDir: "assets",
emptyOutDir: true, emptyOutDir: true,
}, },
resolve: { resolve: {
alias: { alias: {
"@": path.resolve(__dirname, "./src"), "@": path.resolve(__dirname, "./src"),
}, },
}, },
server: { server: {
port: 5500, port: 5500,
host: true, host: true,
allowedHosts: true, allowedHosts: true,
proxy: { proxy: {
"/lst/api": { "/lst/api": {
target: `http://localhost:${Number( target: `http://localhost:${Number(process.env.VITE_PORT || 4000)}`,
process.env.VITE_PORT || 4000 changeOrigin: true,
)}`, secure: false,
changeOrigin: true, },
secure: false, "/lst/ws": {
}, target: `ws://localhost:${Number(process.env.VITE_PORT || 4000)}`, // Your Go WebSocket endpoint
"/lst/ws": { ws: true,
target: `ws://localhost:${Number( changeOrigin: true,
process.env.VITE_PORT || 4000 secure: false,
)}`, // Your Go WebSocket endpoint rewrite: (path) => path.replace(/^\/ws/, ""),
ws: true, },
changeOrigin: true, // Proxy docs to Docusaurus
secure: false, "/lst/d": {
rewrite: (path) => path.replace(/^\/ws/, ""), target: `http://localhost:4300`,
}, changeOrigin: true,
// Proxy docs to Docusaurus //rewrite: (path) => path.replace(/^\/lst\/d/, "/"),
"/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-query": "^5.81.2",
"@tanstack/react-router": "^1.121.34", "@tanstack/react-router": "^1.121.34",
"@tanstack/react-table": "^8.21.3", "@tanstack/react-table": "^8.21.3",
"better-auth": "^1.3.28",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",

View File

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