Push with router.refresh

This commit is contained in:
Mitchell Magro 2025-07-09 18:57:00 +02:00
parent fc4be718f7
commit 16d51f30b5
8 changed files with 201 additions and 96 deletions

View File

@ -1,66 +1,127 @@
// app/api/user/route.ts // app/api/user/route.ts
import { NextResponse } from "next/server"; import { NextRequest, NextResponse } from "next/server";
export const users = [
{
merchantId: 100987998,
id: "bc6a8a55-13bc-4538-8255-cd0cec3bb4e9",
mame: "Jacob",
username: "lspaddy",
firstName: "Paddy",
lastName: "Man",
email: "patrick@omegasys.eu",
phone: "",
jobTitle: "",
enabled: true,
authorities: [
"ROLE_IIN",
"ROLE_FIRST_APPROVER",
"ROLE_RULES_ADMIN",
"ROLE_TRANSACTION_VIEWER",
"ROLE_IIN_ADMIN",
"ROLE_USER_PSP_ACCOUNT",
],
allowedMerchantIds: [100987998],
created: "2025-05-04T15:32:48.432Z",
disabledBy: null,
disabledDate: null,
disabledReason: null,
incidentNotes: false,
lastLogin: "",
lastMandatoryUpdated: "2025-05-04T15:32:48.332Z",
marketingNewsletter: false,
releaseNotes: false,
requiredActions: ["CONFIGURE_TOTP", "UPDATE_PASSWORD"],
twoFactorCondition: "required",
twoFactorCredentials: [],
},
{
merchantId: 100987998,
mame: "Jacob",
id: "382eed15-1e21-41fa-b1f3-0c1adb3af714",
username: "lsterence",
firstName: "Terence",
lastName: "User",
email: "terence@omegasys.eu",
phone: "",
jobTitle: "",
enabled: true,
authorities: ["ROLE_IIN", "ROLE_FIRST_APPROVER", "ROLE_RULES_ADMIN"],
allowedMerchantIds: [100987998],
created: "2025-05-04T15:32:48.432Z",
disabledBy: null,
disabledDate: null,
disabledReason: null,
incidentNotes: false,
lastLogin: "",
lastMandatoryUpdated: "2025-05-04T15:32:48.332Z",
marketingNewsletter: false,
releaseNotes: false,
requiredActions: ["CONFIGURE_TOTP", "UPDATE_PASSWORD"],
twoFactorCondition: "required",
twoFactorCredentials: [],
},
];
export async function GET() { export async function GET() {
return NextResponse.json([ return NextResponse.json(users);
{
merchantId: 100987998,
id: "bc6a8a55-13bc-4538-8255-cd0cec3bb4e9",
mame: "Jacob",
username: "lspaddy",
firstName: "Paddy",
lastName: "Man",
email: "patrick@omegasys.eu",
phone: "",
jobTitle: "",
enabled: true,
authorities: [
"ROLE_IIN",
"ROLE_FIRST_APPROVER",
"ROLE_RULES_ADMIN",
"ROLE_TRANSACTION_VIEWER",
"ROLE_IIN_ADMIN",
"ROLE_USER_PSP_ACCOUNT",
],
allowedMerchantIds: [100987998],
created: "2025-05-04T15:32:48.432Z",
disabledBy: null,
disabledDate: null,
disabledReason: null,
incidentNotes: false,
lastLogin: "",
lastMandatoryUpdated: "2025-05-04T15:32:48.332Z",
marketingNewsletter: false,
releaseNotes: false,
requiredActions: ["CONFIGURE_TOTP", "UPDATE_PASSWORD"],
twoFactorCondition: "required",
twoFactorCredentials: [],
},
{
merchantId: 100987998,
mame: "Jacob",
id: "382eed15-1e21-41fa-b1f3-0c1adb3af714",
username: "lsterence",
firstName: "Terence",
lastName: "User",
email: "terence@omegasys.eu",
phone: "",
jobTitle: "",
enabled: true,
authorities: ["ROLE_IIN", "ROLE_FIRST_APPROVER", "ROLE_RULES_ADMIN"],
allowedMerchantIds: [100987998],
created: "2025-05-04T15:32:48.432Z",
disabledBy: null,
disabledDate: null,
disabledReason: null,
incidentNotes: false,
lastLogin: "",
lastMandatoryUpdated: "2025-05-04T15:32:48.332Z",
marketingNewsletter: false,
releaseNotes: false,
requiredActions: ["CONFIGURE_TOTP", "UPDATE_PASSWORD"],
twoFactorCondition: "required",
twoFactorCredentials: [],
},
]);
} }
export async function POST(request: NextRequest) {
const body = await request.json();
// Use the first user as a template
const templateUser = users[0];
// Create the new user by spreading the template and then the body (body fields override template)
const newUser = {
...templateUser,
...body,
id:
typeof crypto !== "undefined" && crypto.randomUUID
? crypto.randomUUID()
: Math.random().toString(36).substring(2, 15),
created: new Date().toISOString(),
};
users.push(newUser);
return NextResponse.json(newUser, { status: 201 });
}
// To call the POST function from the client side, you can use fetch like this:
/*
Example usage in a React component or any client-side JS:
const createUser = async (userData) => {
const res = await fetch('/api/dashboard/admin/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(userData),
});
if (!res.ok) {
// handle error
throw new Error('Failed to create user');
}
const newUser = await res.json();
return newUser;
};
// Usage:
createUser({
username: "newuser",
firstName: "New",
lastName: "User",
email: "newuser@example.com",
// ...other fields as needed
}).then(user => {
console.log('Created user:', user);
}).catch(err => {
console.error(err);
});
*/

View File

@ -1,12 +1,15 @@
import Users from "@/app/features/Pages/Admin/Users/users"; import Users from "@/app/features/Pages/Admin/Users/users";
export default async function BackOfficeUsersPage() { export default async function BackOfficeUsersPage() {
const res = await fetch("http://localhost:3000/api/dashboard/admin/users", { const baseUrl =
process.env.NEXT_PUBLIC_BASE_URL || process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: "http://localhost:3000";
const res = await fetch(`${baseUrl}/api/dashboard/admin/users`, {
cache: "no-store", // 👈 disables caching for SSR freshness cache: "no-store", // 👈 disables caching for SSR freshness
}); });
const users = await res.json(); const users = await res.json();
console.log("[USERS]", users);
return ( return (
<div> <div>
<Users users={users} /> <Users users={users} />

View File

@ -1,23 +1,11 @@
import React from "react"; import React from "react";
import "./editUser.scss"; import { useRouter } from "next/navigation";
import { IEditUserForm, EditUserField } from "../User.interfaces";
// Union type for form field names import { createRole } from "@/services/roles.services";
export type EditUserField = import "./EditUser.scss";
| "firstName"
| "lastName"
| "email"
| "role"
| "phone";
interface IEditUserForm {
firstName: string;
lastName: string;
email: string;
role: string;
phone: string;
}
const EditUser = () => { const EditUser = () => {
const router = useRouter();
const [form, setForm] = React.useState<IEditUserForm>({ const [form, setForm] = React.useState<IEditUserForm>({
firstName: "", firstName: "",
lastName: "", lastName: "",
@ -53,8 +41,20 @@ const EditUser = () => {
}); });
}; };
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
try {
await createRole(form);
router.refresh(); // <- refreshes the page (SSR re-runs)
} catch (err: any) {
console.log(err.message || "Error creating role");
// setError(err.message || "Error creating role");
}
};
return ( return (
<form className="edit-user"> <form className="edit-user" onSubmit={handleSubmit}>
<input <input
type="text" type="text"
placeholder="First Name" placeholder="First Name"

View File

@ -0,0 +1,14 @@
export interface IEditUserForm {
firstName: string;
lastName: string;
email: string;
role: string;
phone: string;
}
export type EditUserField =
| "firstName"
| "lastName"
| "email"
| "role"
| "phone";

View File

@ -1,6 +1,17 @@
.edit-user { .user-card {
display: flex; &__edit {
justify-content: center; display: flex;
align-items: center; justify-content: center;
width: 100%; align-items: center;
width: 100%;
}
&__edit-transition {
opacity: 0;
transition: opacity 0.5s ease-in-out;
&--open {
opacity: 1;
}
}
} }

View File

@ -1,3 +1,4 @@
import { useState } from "react";
import { import {
Card, Card,
CardContent, CardContent,
@ -18,8 +19,8 @@ import {
AdminPanelSettings, AdminPanelSettings,
History, History,
} from "@mui/icons-material"; } from "@mui/icons-material";
import { useState } from "react";
import EditUser from "./EditUser/EditUser"; import EditUser from "./EditUser/EditUser";
import "./User.scss";
interface Props { interface Props {
username: string; username: string;
@ -99,7 +100,7 @@ export default function UserRoleCard({
<Box mt={2}> <Box mt={2}>
<Typography fontWeight="bold"> <Typography fontWeight="bold">
Roles{" "} Roles
<Tooltip title="Roles assigned to this user"> <Tooltip title="Roles assigned to this user">
<InfoOutlined fontSize="small" /> <InfoOutlined fontSize="small" />
</Tooltip> </Tooltip>
@ -113,13 +114,13 @@ export default function UserRoleCard({
{extraRolesCount && <Chip label={`+${extraRolesCount}`} />} {extraRolesCount && <Chip label={`+${extraRolesCount}`} />}
</Stack> </Stack>
</Box> </Box>
{isEditing && <EditUser />} <div
{/* Footer */} className={`user-card__edit-transition${
{/* <Box mt={2}> isEditing ? " user-card__edit-transition--open" : ""
<Typography variant="caption" color="text.secondary"> }`}
{lastLogin} >
</Typography> {isEditing && <EditUser />}
</Box> */} </div>
</CardContent> </CardContent>
</Card> </Card>
); );

View File

@ -0,0 +1,15 @@
import { IEditUserForm } from "@/app/features/UserRoles/User.interfaces";
export async function createRole(data: IEditUserForm) {
const res = await fetch("/api/dashboard/admin/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
if (!res.ok) {
throw new Error("Failed to create role");
}
return res.json(); // or return type depending on your backend
}