Skip to content

Commit dff7471

Browse files
committed
set management role page completely
1 parent 441c67f commit dff7471

30 files changed

Lines changed: 963 additions & 93 deletions

File tree

public/Icons/index.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,23 @@ export default function Icons(props: IconsProps) {
10961096
<path d="M9 12H7V14H9V12ZM17 12H15V14H17V12Z" fill="#FFFFFF" />
10971097
</svg>
10981098
)
1099+
case 'active':
1100+
return (
1101+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
1102+
<circle cx="12" cy="12" r="10" stroke="#4CAF50" stroke-width="2" fill="#4CAF50" />
1103+
<path d="M8 12.5L11 15.5L16 9" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
1104+
</svg>
1105+
1106+
)
1107+
case 'inactive':
1108+
return (
1109+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
1110+
<circle cx="12" cy="12" r="10" stroke="#FF5722" stroke-width="2" fill="#FF5722" />
1111+
<path d="M8 8L16 16" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
1112+
<path d="M16 8L8 16" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
1113+
</svg>
1114+
1115+
)
10991116
case 'card':
11001117
return (
11011118
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { UserDtoResponse } from '@/store/userManagement/user.interface';
2+
import { UserRole } from '@/store/userProfile/interface';
3+
import { NextRequest, NextResponse } from 'next/server';
4+
5+
export async function POST(req: NextRequest) {
6+
const data : UserDtoResponse = {
7+
email: 'Saghar@gmail.com',
8+
isActive: false,
9+
role: UserRole.User,
10+
userId: 2
11+
}
12+
13+
return NextResponse.json({ message: 'Add user successfully', data }, { status: 200 });
14+
15+
}
16+
17+
18+
export function GET() {
19+
return NextResponse.json({ message: 'Method not allowed' }, { status: 405 });
20+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
import { UserDtoResponse } from '@/store/userManagement/user.interface';
3+
import { UserRole } from '@/store/userProfile/interface';
4+
import { NextRequest, NextResponse } from 'next/server';
5+
6+
export async function PUT(req: NextRequest) {
7+
const { role } = await req.json();
8+
const data : UserDtoResponse = {
9+
email: 'Saghar@gmail.com',
10+
isActive: false,
11+
role: role,
12+
userId: 2
13+
}
14+
15+
return NextResponse.json({ message: 'Update user successfully', data }, { status: 200 });
16+
17+
}
18+
19+
20+
export function GET() {
21+
return NextResponse.json({ message: 'Method not allowed' }, { status: 405 });
22+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { UserDtoResponse } from '@/store/userManagement/user.interface';
2+
import { UserRole } from '@/store/userProfile/interface';
3+
import { NextRequest, NextResponse } from 'next/server';
4+
5+
export async function GET(req: NextRequest) {
6+
const data : Array<UserDtoResponse> = [{
7+
email: 'Connor@gmail.com',
8+
isActive: false,
9+
role: UserRole.Admin,
10+
userId: 2
11+
},
12+
{
13+
email: 'Saghar@gmail.com',
14+
isActive: false,
15+
role: UserRole.User,
16+
userId: 3
17+
},{
18+
email: 'Yannies@gmail.com',
19+
isActive: true,
20+
role: UserRole.Developer,
21+
userId: 4
22+
}]
23+
24+
25+
return NextResponse.json({ message: 'Add user successfully', data }, { status: 200 });
26+
27+
}
28+
29+
30+
export function POST() {
31+
return NextResponse.json({ message: 'Method not allowed' }, { status: 405 });
32+
}
Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,52 @@
1+
'use client'
12
import Management from "@/app/components/Management";
3+
import Sidebar from "@/app/components/Sidebar";
4+
import { useShowInnerComponent } from "@/app/ShowInnerComponentContext";
5+
import isMobileView from "@/app/utils/isMobileView";
6+
import Icons from "../../../../public/Icons";
7+
import { useRouter } from "next/navigation";
8+
import { useState } from "react";
9+
import defaultSidebarStatus from "@/app/utils/defaultSidebarStatus";
210

311
export default function ManagementPage() {
12+
const { setShowInnerComponent } = useShowInnerComponent();
13+
const [isSidebarOpen, setIsSidebarOpen] = useState<boolean>(defaultSidebarStatus);
14+
const router = useRouter();
15+
416
return (
5-
<Management />
17+
<>
18+
{isMobileView ? (
19+
<div className={'text-secondary-17 bg-secondary-02' + `${isMobileView ? ' w-screen h-screen' : ''}`}>
20+
<div className={'bg-secondary-01 px-3 py-9' + ` ${isMobileView ? 'space-y-3' : 'hidden'}`}>
21+
{isMobileView &&
22+
<div className={'mb-8'}>
23+
<button
24+
className={'absolute'}
25+
onClick={() => { setShowInnerComponent(false)}}
26+
>
27+
<Icons name={'right-arrow-key'} />
28+
</button>
29+
<h1 className={'font-bold w-fit m-auto'}>Management</h1>
30+
</div>
31+
}
32+
33+
</div>
34+
35+
<Management/>
36+
37+
</div>
38+
39+
) : (
40+
<Sidebar isSidebarOpen={isSidebarOpen} setIsSidebarOpen={setIsSidebarOpen}
41+
children={<>
42+
43+
<Management/>
44+
45+
</>} />
46+
)}
47+
</>
48+
49+
50+
651
)
752
}
Lines changed: 119 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,103 @@
11
import Icons from "../../../../../public/Icons";
22
import IInput from "@/app/components/Common/Input";
3-
import React, { ChangeEvent, useEffect, useState } from "react";
3+
import React, { useEffect, useState } from "react";
44
import IButton from "@/app/components/Common/Button";
5-
import checkPasswordFormat from "@/app/utils/checkPasswordFormat";
6-
import { useDispatch, useSelector } from "react-redux";
7-
import toast from "react-hot-toast";
8-
import IModal from "@/app/components/Common/Modal";
95
import isMobileView from "@/app/utils/isMobileView";
10-
import { RoleManagementProps, User } from "./interface";
6+
import { User } from "./interface";
117
import PasswordInputWithToggle from "./PasswordInputWithToggle";
8+
import { UserRole } from "@/store/userProfile/interface";
9+
import { useDispatch, useSelector } from "react-redux";
10+
import { fetchUserManagementResponse } from "@/store/userManagement/new/slice";
11+
import toast from "react-hot-toast";
12+
import { updateUserRequest } from "@/store/userManagement/update/slice";
13+
import { fetchUserList } from "@/store/userManagement/list/slice";
14+
import { UserDtoResponse } from "@/store/userManagement/user.interface";
1215

1316
export default function RoleManagement() {
14-
const [users, setUsers] = useState<User[]>([
15-
// Initial users can be fetched from an API or predefined
16-
{ email: "manager@example.com", password: "manager123" },
17-
{ email: "user@example.com", password: "user123" },
18-
]);
19-
const [newUser, setNewUser] = useState<User>({ email: '', password: '' });
17+
const [users, setUsers] = useState<UserDtoResponse[]>([]);
18+
const [newUser, setNewUser] = useState<User>({ email: '', password: '', role: UserRole.Guest });
2019
const [showPasswords, setShowPasswords] = useState<{ [key: number]: boolean }>({});
2120
const [passwordType, setPasswordType] = useState<string>('password');
21+
const [isValid, setIsValid] = useState<boolean>();
22+
23+
const dispatch = useDispatch();
24+
const userManagementState = useSelector((state: any) => state.userManagement);
25+
const updateUserState = useSelector((state: any) => state.updateUser);
26+
const userListState = useSelector((state: any) => state.userList);
27+
28+
function handleInputChange(e: React.ChangeEvent<HTMLInputElement>) {
29+
const value = e.target.value;
30+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
31+
setNewUser({ ...newUser, email: e.target.value })
32+
setIsValid(emailRegex.test(value));
33+
34+
}
35+
useEffect(() => {
36+
dispatch(fetchUserList());
37+
}, []);
2238

39+
useEffect(() => {
40+
if (userListState.isDone && userListState.response){
41+
if(userListState.response.data)
42+
setUsers(userListState.response.data)
43+
}
44+
}, [userListState.isDone, userListState.response]);
45+
46+
useEffect(() => {
47+
if (userManagementState.isDone && userManagementState.response) {
48+
if (userManagementState.response.data.userId) {
49+
setUsers([...users, userManagementState.response.data]);
50+
setNewUser({ email: '', password: '', role: UserRole.Guest });
51+
toast.success('user has been added successfully');
52+
}
53+
}
54+
}, [userManagementState.isDone, userManagementState.response]);
55+
56+
useEffect(() => {
57+
if (updateUserState.isDone && updateUserState.response) {
58+
toast.success('user has been updated successfully');
59+
}
60+
}, [updateUserState.isDone, updateUserState.response]);
2361

2462
const handleAddUser = () => {
25-
if (newUser.email && newUser.password) {
26-
setUsers([...users, newUser]);
27-
setNewUser({ email: '', password: '' });
63+
if (isValid && newUser.email && newUser.password && newUser.role !== UserRole.Guest) {
64+
dispatch(fetchUserManagementResponse(newUser))
2865
}
2966
};
3067

31-
const togglePasswordVisibility = (index: number) => {
32-
setShowPasswords({ ...showPasswords, [index]: !showPasswords[index] });
68+
const handleRoleChange = (index: number, newRole: UserRole) => {
69+
const updatedUsers = users.map((user, i) =>
70+
i === index ? { ...user, role: newRole } : user
71+
);
72+
setUsers(updatedUsers);
3373
};
3474

35-
const dispatch = useDispatch();
36-
const editPasswordStates = useSelector((state: any) => state.editPassword)
37-
75+
const handleUserEditSubmit = (index: number) => {
76+
debugger;
77+
const user = users[index];
78+
dispatch(updateUserRequest(user));
3879

39-
useEffect(() => {
40-
if (editPasswordStates?.isDone) {
41-
toast.success('Password has been changed successfully')
42-
}
43-
}, [editPasswordStates]);
80+
};
4481

4582
return (
4683
<>
47-
<div className={'bg-secondary-01 px-3 pb-9' + ` ${isMobileView ? 'space-y-3' : 'rounded-xl'}`}>
84+
<div className={'bg-secondary-01 px-3 pb-9 mb-4' + ` ${isMobileView ? 'space-y-3' : 'rounded-xl'}`}>
4885
<h4 className={'font-semibold center py-2 border-b-2 mb-5'}>Add New User</h4>
4986
<div className={'flex w-full flex-wrap items-end gap-5'}>
50-
5187
<IInput inputId={'email'}
5288
label={'Email'}
5389
value={newUser.email}
54-
onChange={(e) => setNewUser({ ...newUser, email: e.target.value })}
90+
onChange={handleInputChange}
5591
style={'secondaryOutline'}
56-
type={'email'} containerCustomStyle= {'flex-1'}/>
57-
92+
type={'email'} containerCustomStyle={'flex-1'} />
93+
5894
<IInput
5995
label={'Password'}
6096
inputId={'password'}
6197
type={passwordType}
6298
onChange={(e) => setNewUser({ ...newUser, password: e.target.value })}
6399
value={newUser.password}
64-
containerCustomStyle= {'flex-1'}
100+
containerCustomStyle={'flex-1'}
65101
suffix={
66102
<div
67103
className={'cursor-pointer'}
@@ -70,7 +106,26 @@ export default function RoleManagement() {
70106
</div>
71107
}
72108
/>
73-
<IButton style={'primaryOutline'} onClick={handleAddUser}>
109+
<div className="flex-1">
110+
<label className="font-semibold">
111+
Role
112+
</label>
113+
<select
114+
className="flex justify-between items-center h-12 text-sm font-bold p-2 mt-2 rounded-xl bg-transparent text-secondary-17 border border-secondary-02 focus-within:border-primary focus-within:border w-full my-4 cursor-pointer"
115+
value={newUser.role}
116+
onChange={(e) => setNewUser({ ...newUser, role: e.target.value as UserRole })}
117+
>
118+
<option value={UserRole.Guest} disabled>Select...</option>
119+
<option value={UserRole.User}>User</option>
120+
<option value={UserRole.Management}>Management</option>
121+
<option value={UserRole.Admin}>Admin</option>
122+
<option value={UserRole.Developer}>Developer</option>
123+
</select>
124+
</div>
125+
126+
<IButton style={'primaryOutline'}
127+
disabled={!isValid || !newUser.password || !newUser.role}
128+
onClick={handleAddUser}>
74129
<p className={'font-medium'}>Add User</p>
75130
</IButton>
76131
</div>
@@ -81,19 +136,40 @@ export default function RoleManagement() {
81136
<h4 className={'font-semibold center py-2 border-b-2 mb-5'}>Current Users</h4>
82137
<ul className="space-y-4">
83138
{users.map((user, index) => (
84-
<li key={index} className="flex justify-between items-center border-b border-secondary-02 py-2">
85-
<span>{user.email}</span>
86-
<PasswordInputWithToggle
87-
password={user.password}
88-
isVisible={showPasswords[index]}
89-
onToggleVisibility={() => togglePasswordVisibility(index)}
90-
/>
139+
<li key={index} className="flex md:items-center border-b border-secondary-02 py-2 md:flex-row md:justify-between flex-col">
140+
<div className="text-sm flex flex-1">
141+
<Icons name={`${user.isActive ? 'active' : 'inactive'}`} />
142+
<span className="ml-2">{user.email}</span>
143+
</div>
144+
<div className="flex flex-1 md:items-center md:flex-row flex-col">
145+
{/* <PasswordInputWithToggle
146+
password={user.password}
147+
isVisible={showPasswords[index]}
148+
onToggleVisibility={() => togglePasswordVisibility(index)}
149+
/> */}
150+
151+
<select
152+
className="md:my-0 my-2 border border-gray-300 rounded px-2 py-1 md:ml-2 text-xs py-2 cursor-pointer"
153+
value={user.role}
154+
onChange={(e) => handleRoleChange(index, e.target.value as UserRole)}
155+
>
156+
<option value={UserRole.User}>User</option>
157+
<option value={UserRole.Management}>Management</option>
158+
<option value={UserRole.Admin}>Admin</option>
159+
<option value={UserRole.Developer}>Developer</option>
160+
</select>
161+
<IButton
162+
style={'primaryOutline'}
163+
onClick={() => handleUserEditSubmit(index)}
164+
customStyle={'md:ml-2 ml-0 h-auto py-1 text-xs rounded-md'}
165+
>
166+
Save
167+
</IButton>
168+
</div>
91169
</li>
92170
))}
93171
</ul>
94172
</div>
95-
96-
97173
</>
98-
)
99-
}
174+
);
175+
}

src/app/components/Management/RoleManagement/interface.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import { UserRole } from "@/store/userProfile/interface";
2+
13
export interface User {
24
email: string;
35
password: string;
6+
role: UserRole;
47
}
58
export interface RoleManagementProps {
69
setIsEditPasswordOpen: (isOpen: boolean) => void;

0 commit comments

Comments
 (0)