refactor(front end): login fixes to account for the forced password change
This commit is contained in:
32
LogisticsSupportTool_API_DOCS/LstV2/Auth/Get Roles.bru
Normal file
32
LogisticsSupportTool_API_DOCS/LstV2/Auth/Get Roles.bru
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
35
LogisticsSupportTool_API_DOCS/app/auth/Login.bru
Normal file
35
LogisticsSupportTool_API_DOCS/app/auth/Login.bru
Normal 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
|
||||
}
|
||||
@@ -21,4 +21,5 @@ body:json {
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
}
|
||||
|
||||
@@ -32,4 +32,5 @@ script:post-response {
|
||||
|
||||
settings {
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
vars {
|
||||
url: http://localhost:5500
|
||||
session_cookie:
|
||||
urlv2: http://usmcd1vms036:3000
|
||||
urlv2: http://localhost:3000
|
||||
jwtV2:
|
||||
userID:
|
||||
}
|
||||
vars:secret [
|
||||
v2Password
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
@@ -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>
|
||||
}
|
||||
@@ -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>
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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>
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'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't have an account?{" "}
|
||||
<Link to={"/user/signup"} className="underline underline-offset-4">
|
||||
Sign up
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</LstCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
13
frontend/src/routes/(auth)/user/index.tsx
Normal file
13
frontend/src/routes/(auth)/user/index.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
40
frontend/src/routes/(auth)/user/profile.tsx
Normal file
40
frontend/src/routes/(auth)/user/profile.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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/, "/"),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
850
lstV2/frontend/package-lock.json
generated
850
lstV2/frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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",
|
||||
|
||||
@@ -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
17418
lstV2/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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
34
scripts/lstAppMoves.mjs
Normal 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`);
|
||||
Reference in New Issue
Block a user