diff --git a/src/App.css b/src/App.css
index d54ede8..b3eb87f 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,5 +1,5 @@
#root {
- max-width: 1280px;
+
margin: 0 auto;
padding: 2rem;
text-align: center;
diff --git a/src/api/userApi.js b/src/api/userApi.js
index ba07e58..94f56c5 100644
--- a/src/api/userApi.js
+++ b/src/api/userApi.js
@@ -1,4 +1,3 @@
-// src/api/userApi.js
export default class UserApi {
constructor(token) {
this.baseUrl = 'https://thalos-bff.dream-views.com/api/v1/User';
@@ -32,4 +31,40 @@ export default class UserApi {
throw err;
}
}
+
+ // === CREATE a user ===
+ async createUser(userData) {
+ try {
+ const response = await fetch(`${this.baseUrl}/Create`, {
+ method: 'POST',
+ headers: this.getHeaders(),
+ body: JSON.stringify(userData),
+ });
+ if (!response.ok) {
+ throw new Error(`Failed to create user: ${response.status}`);
+ }
+ return await response.json();
+ } catch (err) {
+ console.error('Error creating user:', err);
+ throw err;
+ }
+ }
+
+ // === UPDATE a user ===
+ async updateUser(userData) {
+ try {
+ const response = await fetch(`${this.baseUrl}/Update`, {
+ method: 'PUT',
+ headers: this.getHeaders(),
+ body: JSON.stringify(userData),
+ });
+ if (!response.ok) {
+ throw new Error(`Failed to update user: ${response.status}`);
+ }
+ return await response.json();
+ } catch (err) {
+ console.error('Error updating user:', err);
+ throw err;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/private/users/AddOrEditUserForm.jsx b/src/private/users/AddOrEditUserForm.jsx
index 4d79483..fbacc50 100644
--- a/src/private/users/AddOrEditUserForm.jsx
+++ b/src/private/users/AddOrEditUserForm.jsx
@@ -1,103 +1,192 @@
-import { useState, useEffect } from 'react';
+import { useState, useEffect, useMemo } from 'react';
import { Box, Button, TextField, MenuItem } from '@mui/material';
-import { createExternalData, updateExternalData } from '../../api/mongo/actions';
+import UserApi from '../../api/userApi';
+import { useAuth } from '../../context/AuthContext';
export default function AddOrEditUserForm({ onAdd, initialData, onCancel }) {
- const [formData, setFormData] = useState({
- username: '',
- fullName: '',
+ const { user } = useAuth();
+ const thalosToken = user?.thalosToken || localStorage.getItem('thalosToken');
+ const api = useMemo(() => (thalosToken ? new UserApi(thalosToken) : null), [thalosToken]);
+
+ const [formData, setFormData] = useState({
+ _Id: '',
+ email: '',
+ name: '',
+ middleName: '',
+ lastName: '',
+ tenantId: '',
+ roleId: '',
+ status: 'Active',
+ companies: [],
+ projects: [],
+ sendInvitation: true,
+ });
+
+ useEffect(() => {
+ if (initialData) {
+ setFormData({
+ _Id: initialData._id || initialData._Id || '',
+ email: initialData.email ?? '',
+ name: initialData.name ?? '',
+ middleName: initialData.middleName ?? '',
+ lastName: initialData.lastName ?? '',
+ tenantId: initialData.tenantId ?? '',
+ roleId: initialData.roleId ?? '',
+ status: initialData.status ?? 'Active',
+ companies: Array.isArray(initialData.companies) ? initialData.companies : [],
+ projects: Array.isArray(initialData.projects) ? initialData.projects : [],
+ sendInvitation: true,
+ });
+ } else {
+ setFormData({
+ _Id: '',
email: '',
- role: 'User',
- status: 'Active'
- });
+ name: '',
+ middleName: '',
+ lastName: '',
+ tenantId: '',
+ roleId: '',
+ status: 'Active',
+ companies: [],
+ projects: [],
+ sendInvitation: true,
+ });
+ }
+ }, [initialData]);
- useEffect(() => {
- if (initialData) {
- setFormData({ ...initialData });
- } else {
- setFormData({
- username: '',
- fullName: '',
- email: '',
- role: 'User',
- status: 'Active'
- });
- }
- }, [initialData]);
+ const handleChange = (e) => {
+ const { name, value } = e.target;
+ if (name === 'companies' || name === 'projects') {
+ const arr = value.split(',').map(s => s.trim()).filter(s => s.length > 0);
+ setFormData(prev => ({ ...prev, [name]: arr }));
+ } else {
+ setFormData(prev => ({ ...prev, [name]: value }));
+ }
+ };
- const handleChange = (e) => {
- const { name, value } = e.target;
- setFormData(prev => ({ ...prev, [name]: value }));
- };
+ const handleSubmit = async () => {
+ try {
+ if (!api) throw new Error('Missing Thalos token');
- const handleSubmit = async () => {
- try {
- if (initialData) {
- await updateExternalData(formData);
- } else {
- await createExternalData(formData);
- }
- if (onAdd) onAdd();
- } catch (error) {
- console.error('Error submitting form:', error);
- }
- };
+ if (initialData) {
+ // UPDATE (PUT /User/Update) — API requires _Id, remove Id, displayName, tenantId
+ const payload = {
+ _Id: formData._Id,
+ email: formData.email,
+ name: formData.name,
+ middleName: formData.middleName,
+ lastName: formData.lastName,
+ tenantId: formData.tenantId,
+ roleId: formData.roleId,
+ companies: formData.companies,
+ projects: formData.projects,
+ status: formData.status || 'Active',
+ };
+ await api.updateUser(payload);
+ } else {
+ // CREATE (POST /User/Create)
+ const payload = {
+ email: formData.email,
+ name: formData.name,
+ middleName: formData.middleName,
+ lastName: formData.lastName,
+ roleId: formData.roleId,
+ sendInvitation: !!formData.sendInvitation,
+ };
+ await api.createUser(payload);
+ }
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
+ onAdd?.();
+ } catch (error) {
+ console.error('Error submitting form:', error);
+ }
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
}
\ No newline at end of file
diff --git a/src/private/users/UserManagement.jsx b/src/private/users/UserManagement.jsx
index 7e3a992..a1f6290 100644
--- a/src/private/users/UserManagement.jsx
+++ b/src/private/users/UserManagement.jsx
@@ -7,8 +7,8 @@ import DeleteRoundedIcon from '@mui/icons-material/DeleteRounded';
import AddOrEditUserForm from './AddOrEditUserForm';
import UserApi from '../../api/userApi';
import { useAuth } from '../../context/AuthContext';
-import { deleteExternalData } from '../../api/mongo/actions';
import useApiToast from '../../hooks/useApiToast';
+import '../../App.css';
const columnsBase = [
{ field: 'email', headerName: 'Email', width: 260 },
@@ -88,7 +88,22 @@ export default function UserManagement() {
const handleEditClick = (params) => {
if (!params || !params.row) return;
- setEditingData(params.row);
+ const r = params.row;
+ const normalized = {
+ _id: r._id || r._Id || '',
+ id: r.id || r.Id || '',
+ email: r.email ?? '',
+ name: r.name ?? '',
+ middleName: r.middleName ?? '',
+ lastName: r.lastName ?? '',
+ displayName: r.displayName ?? '',
+ tenantId: r.tenantId ?? '',
+ roleId: r.roleId ?? '',
+ status: r.status ?? 'Active',
+ companies: Array.isArray(r.companies) ? r.companies : [],
+ projects: Array.isArray(r.projects) ? r.projects : [],
+ };
+ setEditingData(normalized);
setOpen(true);
};
@@ -100,7 +115,22 @@ export default function UserManagement() {
const handleConfirmDelete = async () => {
try {
- await deleteExternalData(rowToDelete?._id);
+ if (!apiRef.current || !rowToDelete?._id) throw new Error('Missing API or user id');
+
+ const payload = {
+ _Id: rowToDelete._id || rowToDelete._Id,
+ Id: rowToDelete.id || rowToDelete.Id,
+ email: rowToDelete.email ?? '',
+ name: rowToDelete.name ?? '',
+ middleName: rowToDelete.middleName ?? '',
+ lastName: rowToDelete.lastName ?? '',
+ roleId: rowToDelete.roleId ?? '',
+ companies: Array.isArray(rowToDelete.companies) ? rowToDelete.companies : [],
+ projects: Array.isArray(rowToDelete.projects) ? rowToDelete.projects : [],
+ status: 'Inactive',
+ };
+
+ await apiRef.current.updateUser(payload);
await loadData();
} catch (error) {
console.error('Delete failed:', error);
@@ -164,12 +194,11 @@ export default function UserManagement() {
return (
- User Management
-