Fixed Build
This commit is contained in:
parent
a62faab6b5
commit
4f05061411
@ -24,7 +24,14 @@ export async function POST(request: Request) {
|
||||
let mustChangePassword = false;
|
||||
try {
|
||||
const payload = decodeJwt(token);
|
||||
mustChangePassword = payload.MustChangePassword || false;
|
||||
const mustChangeClaim = payload.MustChangePassword;
|
||||
if (typeof mustChangeClaim === "boolean") {
|
||||
mustChangePassword = mustChangeClaim;
|
||||
} else if (typeof mustChangeClaim === "string") {
|
||||
mustChangePassword = mustChangeClaim.toLowerCase() === "true";
|
||||
} else {
|
||||
mustChangePassword = false;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("❌ Failed to decode current JWT:", err);
|
||||
}
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
import { NextResponse } from "next/server";
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
import { NextResponse, type NextRequest } from "next/server";
|
||||
import { cookies } from "next/headers";
|
||||
|
||||
const BE_BASE_URL = process.env.BE_BASE_URL || "http://localhost:8583";
|
||||
const COOKIE_NAME = "auth_token";
|
||||
|
||||
export async function PUT(
|
||||
request: Request,
|
||||
{ params }: { params: { id: string } }
|
||||
request: NextRequest,
|
||||
context: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const { id } = params;
|
||||
const { id } = await context.params;
|
||||
|
||||
if (!id) {
|
||||
return NextResponse.json(
|
||||
@ -39,15 +41,14 @@ export async function PUT(
|
||||
}
|
||||
);
|
||||
|
||||
// Attempt to parse JSON; fall back to status-only response
|
||||
let data: unknown = null;
|
||||
let data;
|
||||
try {
|
||||
data = await resp.json();
|
||||
} catch {
|
||||
data = { success: resp.ok };
|
||||
}
|
||||
|
||||
return NextResponse.json(data ?? { success: resp.ok }, {
|
||||
return NextResponse.json(data, {
|
||||
status: resp.status,
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
|
||||
@ -63,10 +63,10 @@ function transformUserUpdateData(updates: Record<string, unknown>): {
|
||||
|
||||
export async function PUT(
|
||||
request: Request,
|
||||
{ params }: { params: { id: string } }
|
||||
context: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const { id } = await params;
|
||||
const { id } = await context.params;
|
||||
const body = await request.json();
|
||||
|
||||
// Transform the request body to match backend format
|
||||
@ -108,10 +108,10 @@ export async function PUT(
|
||||
|
||||
export async function DELETE(
|
||||
_request: Request,
|
||||
{ params }: { params: { id: string } }
|
||||
context: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const { id } = await params;
|
||||
const { id } = await context.params;
|
||||
const { cookies } = await import("next/headers");
|
||||
const cookieStore = await cookies();
|
||||
const token = cookieStore.get(COOKIE_NAME)?.value;
|
||||
|
||||
@ -5,10 +5,10 @@ const COOKIE_NAME = "auth_token";
|
||||
|
||||
export async function PUT(
|
||||
request: NextRequest,
|
||||
{ params }: { params: { id: string } }
|
||||
context: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const { id } = await params;
|
||||
const { id } = await context.params;
|
||||
const { cookies } = await import("next/headers");
|
||||
const cookieStore = await cookies();
|
||||
const token = cookieStore.get(COOKIE_NAME)?.value;
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
/**
|
||||
* Placeholder Settings API route.
|
||||
* Keeps the module valid while the real implementation
|
||||
* is being built, and makes the intent obvious to clients.
|
||||
*/
|
||||
export async function GET() {
|
||||
return NextResponse.json(
|
||||
{ message: "Settings endpoint not implemented" },
|
||||
{ status: 501 }
|
||||
);
|
||||
}
|
||||
@ -4,7 +4,7 @@ import React from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { Button, Box, Typography, Stack } from "@mui/material";
|
||||
import { AppDispatch } from "@/app/redux/types";
|
||||
import { autoLogout, refreshAuthStatus } from "@/app/redux/auth/authSlice";
|
||||
import { autoLogout, validateAuth } from "@/app/redux/auth/authSlice";
|
||||
|
||||
export default function TestTokenExpiration() {
|
||||
const dispatch = useDispatch<AppDispatch>();
|
||||
@ -14,7 +14,7 @@ export default function TestTokenExpiration() {
|
||||
};
|
||||
|
||||
const handleRefreshAuth = () => {
|
||||
dispatch(refreshAuthStatus());
|
||||
dispatch(validateAuth());
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@ -22,7 +22,6 @@ export default function AllTransactionPage() {
|
||||
transactions: TransactionRow[];
|
||||
total: number;
|
||||
}>({ transactions: [], total: 0 });
|
||||
const [totalRows, setRowCount] = useState(0);
|
||||
const extraColumns: string[] = []; // static for now
|
||||
|
||||
// Memoize rows to avoid new reference each render
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const normalizeValue = (input: any): string => {
|
||||
if (input == null) return "";
|
||||
if (typeof input === "string" || typeof input === "number")
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useEffect, useCallback, useMemo } from "react";
|
||||
import React, { useState, useCallback, useMemo } from "react";
|
||||
import { DataGrid, GridPaginationModel } from "@mui/x-data-grid";
|
||||
import { Box, Paper, Alert } from "@mui/material";
|
||||
import DataTableHeader from "./DataTableHeader";
|
||||
|
||||
@ -31,6 +31,8 @@ const SettingsAccountSecurity: React.FC = () => {
|
||||
currentPassword: passwordData.currentPassword,
|
||||
})
|
||||
);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (err: any) {
|
||||
// Error handling is now done by the epic
|
||||
console.error("Password change error:", err);
|
||||
|
||||
@ -20,11 +20,9 @@ const SettingsPageClient: React.FC = () => {
|
||||
<Box sx={{ display: "flex", gap: 3 }}>
|
||||
<SettingsSidebar
|
||||
active={activeSection}
|
||||
onChange={(
|
||||
section:
|
||||
| string
|
||||
| ((prevState: "personal" | "account") => "personal" | "account")
|
||||
) => setActiveSection(section)}
|
||||
onChange={(section: "personal" | "account") =>
|
||||
setActiveSection(section)
|
||||
}
|
||||
/>
|
||||
|
||||
<Box sx={{ flex: 1 }}>
|
||||
|
||||
@ -47,6 +47,7 @@ const DeleteUser: React.FC<DeleteUserProps> = ({ open, onClose, user }) => {
|
||||
(resultAction.payload as string) || "Failed to delete user"
|
||||
);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (error: any) {
|
||||
toast.error(error.message || "An unexpected error occurred");
|
||||
}
|
||||
|
||||
@ -2,14 +2,14 @@
|
||||
|
||||
import { useEffect } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { initializeAuth } from "./auth/authSlice";
|
||||
import { validateAuth } from "./auth/authSlice";
|
||||
import { AppDispatch } from "./types";
|
||||
|
||||
export function InitializeAuth() {
|
||||
const dispatch = useDispatch<AppDispatch>();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(initializeAuth());
|
||||
dispatch(validateAuth());
|
||||
}, [dispatch]);
|
||||
|
||||
return null;
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { Provider } from "react-redux";
|
||||
import { store } from "./store";
|
||||
import { checkAuthStatus } from "./auth/authSlice";
|
||||
import { validateAuth } from "./auth/authSlice";
|
||||
|
||||
export default function ReduxProvider({
|
||||
children,
|
||||
@ -16,17 +16,17 @@ export default function ReduxProvider({
|
||||
useEffect(() => {
|
||||
// Check authentication status when the ReduxProvider component mounts on the client.
|
||||
// This ensures your Redux auth state is synced with the server-side token.
|
||||
store.dispatch(checkAuthStatus());
|
||||
store.dispatch(validateAuth());
|
||||
|
||||
// Do an additional check after 2 seconds to ensure we have the latest token info
|
||||
initialCheckRef.current = setTimeout(() => {
|
||||
store.dispatch(checkAuthStatus());
|
||||
store.dispatch(validateAuth());
|
||||
}, 2000);
|
||||
|
||||
// Set up periodic token validation every 5 minutes
|
||||
intervalRef.current = setInterval(
|
||||
() => {
|
||||
store.dispatch(checkAuthStatus());
|
||||
store.dispatch(validateAuth());
|
||||
},
|
||||
5 * 60 * 1000
|
||||
); // 5 minutes
|
||||
|
||||
@ -5,6 +5,7 @@ import toast from "react-hot-toast";
|
||||
import { filter, switchMap } from "rxjs/operators";
|
||||
import { of } from "rxjs";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const changePasswordEpic: Epic<any, any, RootState> = action$ =>
|
||||
action$.pipe(
|
||||
// Listen for any action related to changePassword (pending, fulfilled, rejected)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user