Skip to content

Commit f4f2f03

Browse files
committed
create organiztion features
1 parent 738e4ac commit f4f2f03

File tree

34 files changed

+1415
-110
lines changed

34 files changed

+1415
-110
lines changed

src/app/app.routes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ export const routes: Routes = [
144144
import('./features/organization/organization.module').then(
145145
(m) => m.OrganizationModule
146146
),
147-
data: { roles: ['ROLE_ADMIN'] },
147+
data: { roles: ['ADMIN'] },
148148
canActivate: [RoleGuard],
149149
},
150150
],

src/app/core/guards/router-protected/role.guard.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ export class RoleGuard implements CanActivate {
2727
| Observable<boolean | UrlTree>
2828
| Promise<boolean | UrlTree> {
2929
const expectedRoles = next.data['roles'] as string[]; // lấy roles từ route
30-
const userRole = decodeJWT(localStorage.getItem('token') ?? '')?.payload
31-
.scope;
30+
const userRoles = decodeJWT(localStorage.getItem('token') ?? '')?.payload
31+
.roles;
3232

3333
if (!expectedRoles || expectedRoles.length === 0) {
3434
return true; // không yêu cầu role -> cho vào
3535
}
3636

37-
if (expectedRoles.includes(userRole)) {
37+
if (userRoles && userRoles.some((role) => expectedRoles.includes(role))) {
3838
return true;
3939
} else {
4040
sendNotification(
@@ -60,7 +60,7 @@ export class RoleGuard implements CanActivate {
6060
import('./features/service-payment/service-and-payment.module').then(
6161
(m) => m.ServiceAndPaymentModule
6262
),
63-
data: { roles: ['ROLE_ADMIN'] },
63+
data: { roles: ['ADMIN'] },
6464
canActivate: [RoleGuard],
6565
},
6666

src/app/core/models/organization.model.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { IPaginationResponse } from './api-response';
2+
import { UserBasicInfo } from './exercise.model';
3+
14
export type OrganizationInfo = {
25
id: string;
36
name: string;
@@ -9,3 +12,68 @@ export type OrganizationInfo = {
912
logoUrl: string | null;
1013
status: number; // 0 Active, 1 Inactive, 2 Pending
1114
};
15+
16+
export type CreateOrgRequest = {
17+
name: string;
18+
description: string;
19+
email: string;
20+
phone: string;
21+
address: string;
22+
status: string;
23+
logo: File;
24+
};
25+
26+
//Search response
27+
export type MemberResponse = {
28+
user: UserBasicInfo;
29+
role: string;
30+
active: boolean;
31+
};
32+
33+
export type BlockResponse = {
34+
id: string;
35+
orgId: string;
36+
name: string;
37+
code: string;
38+
description: string;
39+
createdAt: string;
40+
updatedAt: string;
41+
members: IPaginationResponse<MemberResponse[]>;
42+
};
43+
44+
export type OrganizationResponse = {
45+
id: string;
46+
name: string;
47+
description: string;
48+
logoUrl: string | null;
49+
email: string;
50+
phone: string;
51+
address: string;
52+
status: string;
53+
createdAt: string;
54+
updatedAt: string;
55+
blocks: IPaginationResponse<BlockResponse[]>;
56+
};
57+
58+
//filter
59+
export type FilterOrgs = {
60+
q?: string;
61+
status?: string;
62+
includeBlocks?: boolean;
63+
blocksPage?: number;
64+
blocksSize?: number;
65+
membersPage?: number;
66+
membersSize?: number;
67+
activeOnlyMembers?: boolean;
68+
includeUnassigned?: boolean;
69+
};
70+
71+
//edit basic info
72+
export type EditOrgRequest = {
73+
description?: string;
74+
email?: string;
75+
phone?: string;
76+
address?: string;
77+
status?: string;
78+
logo?: File;
79+
};

src/app/core/router-manager/horizontal-menu.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { SidebarItem } from '../models/data-handle';
22

3-
export function getNavHorizontalItems(role: string): SidebarItem[] {
4-
const auth_lv1 = ['ROLE_ADMIN', 'ROLE_TEACHER'];
5-
const auth_lv2 = ['ROLE_ADMIN'];
3+
export function getNavHorizontalItems(roles: string[]): SidebarItem[] {
4+
const auth_lv1 = ['ADMIN', 'TEACHER'];
5+
const auth_lv2 = ['ADMIN'];
6+
console.log(roles);
67

78
return [
89
{
@@ -28,20 +29,21 @@ export function getNavHorizontalItems(role: string): SidebarItem[] {
2829
path: 'conversations/chat',
2930
label: 'Tin nhắn',
3031
icon: 'fas fa-comments',
32+
isVisible: !(roles.length !== 0),
3133
},
3234
{
3335
id: 'statistics',
3436
path: '/statistics',
3537
label: 'Thống kê',
3638
icon: 'fas fa-chart-bar',
37-
isVisible: !auth_lv2.includes(role),
39+
isVisible: !roles.includes(auth_lv2[0]),
3840
},
3941
{
4042
id: 'management',
4143
path: 'management/admin',
4244
label: 'Admin quản lý',
4345
icon: 'fas fa-user-shield',
44-
isVisible: !auth_lv2.includes(role),
46+
isVisible: !roles.includes(auth_lv2[0]),
4547
},
4648
{
4749
id: 'payment',
@@ -51,10 +53,10 @@ export function getNavHorizontalItems(role: string): SidebarItem[] {
5153
},
5254
{
5355
id: 'organization ',
54-
path: '/organization/list',
56+
path: '/organization/orgs-list',
5557
label: 'Tổ chức',
5658
icon: 'fa-solid fa-building-user',
57-
isVisible: !auth_lv2.includes(role),
59+
isVisible: !roles.includes(auth_lv2[0]),
5860
},
5961
];
6062
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { SidebarItem } from '../../models/data-handle';
2+
3+
export function sidebarOrgRouter(roles: string[]): SidebarItem[] {
4+
return [
5+
{
6+
id: 'list-orgs',
7+
path: '/organization/orgs-list',
8+
label: 'Nạp tiền',
9+
icon: 'fa-solid fa-tasks',
10+
},
11+
];
12+
}

src/app/core/router-manager/vetical-menu-dynamic/post-vertical-menu.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { SidebarItem } from '../../models/data-handle';
22

3-
export function sidebarPosts(role: string): SidebarItem[] {
3+
export function sidebarPosts(roles: string[]): SidebarItem[] {
44
return [
55
{
66
id: 'saved-posts',
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { Injectable } from '@angular/core';
2+
import { ApiMethod } from '../config-service/api.methods';
3+
import { ApiResponse, IPaginationResponse } from '../../models/api-response';
4+
import { API_CONFIG } from '../config-service/api.enpoints';
5+
import {
6+
CreateOrgRequest,
7+
EditOrgRequest,
8+
FilterOrgs,
9+
OrganizationInfo,
10+
OrganizationResponse,
11+
} from '../../models/organization.model';
12+
import { PostResponse } from '../../models/post.models';
13+
14+
@Injectable({
15+
providedIn: 'root',
16+
})
17+
export class OrganizationService {
18+
constructor(private api: ApiMethod) {}
19+
20+
createOrg(dataCreate: CreateOrgRequest) {
21+
const { logo, ...otherData } = dataCreate;
22+
return this.api.postWithFormData<ApiResponse<null>>(
23+
API_CONFIG.ENDPOINTS.POST.CREATE_ORGANIZATION,
24+
otherData, // các field string
25+
{ logo }
26+
);
27+
}
28+
29+
searchOrgsFilter(page: number, size: number, search?: FilterOrgs) {
30+
const endpoint = API_CONFIG.ENDPOINTS.GET.SEARCH_ORGS_FILTER(
31+
page,
32+
size,
33+
search ? search : null
34+
);
35+
36+
return this.api.get<
37+
ApiResponse<IPaginationResponse<OrganizationResponse[]>>
38+
>(endpoint);
39+
}
40+
41+
getOrgDetails(orgId: string) {
42+
return this.api.get<ApiResponse<OrganizationInfo>>(
43+
API_CONFIG.ENDPOINTS.GET.GET_ORG_DETAILS_BY_ID(orgId)
44+
);
45+
}
46+
47+
editOrg(orgId: string, data: EditOrgRequest) {
48+
return this.api.put<ApiResponse<null>>(
49+
API_CONFIG.ENDPOINTS.PUT.EDIT_ORG(orgId),
50+
data
51+
);
52+
}
53+
54+
deleteOrg(orgId: string) {
55+
return this.api.delete<ApiResponse<null>>(
56+
API_CONFIG.ENDPOINTS.DELETE.DELETE_ORG(orgId)
57+
);
58+
}
59+
}

src/app/core/services/api-service/playground.service.ts

Lines changed: 0 additions & 49 deletions
This file was deleted.

src/app/core/services/config-service/api.enpoints.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { environment } from '../../../../environments/environment';
22
import { EnumType } from '../../models/data-handle';
3+
import { FilterOrgs } from '../../models/organization.model';
34
import { SearchingUser } from '../../models/user.models';
45

56
export const version = '/v1';
@@ -145,6 +146,30 @@ export const API_CONFIG = {
145146
`/payment/purchase-history?page=${page}&size=${size}`,
146147
GET_TRANSACTION_HISTORY: (page: number, size: number) =>
147148
`/payment/history?page=${page}&size=${size}`,
149+
SEARCH_ORGS_FILTER: (
150+
page: number,
151+
size: number,
152+
search: FilterOrgs | null
153+
) => {
154+
let query = `/search/organizations/filter?page=${page}&size=${size}`;
155+
if (search?.includeBlocks)
156+
query += `&includeBlocks=${search.includeBlocks}`;
157+
if (search?.blocksPage && search?.blocksSize)
158+
query += `&blocksPage=${search?.blocksPage}&blocksSize=${search?.blocksSize}`;
159+
if (search?.membersPage && search?.membersSize)
160+
query += `&membersPage=${search?.membersPage}&membersSize=${search?.membersSize}`;
161+
if (search?.activeOnlyMembers)
162+
query += `&activeOnlyMembers=${search?.activeOnlyMembers}`;
163+
if (search?.includeUnassigned)
164+
query += `&includeUnassigned=${search?.includeUnassigned}`;
165+
if (search?.q) query += `&q=${encodeURIComponent(search?.q)}`;
166+
if (search?.status)
167+
query += `&status=${encodeURIComponent(search?.status)}`;
168+
169+
return query;
170+
},
171+
GET_ORG_DETAILS_BY_ID: (orgId: string) =>
172+
`/org/api/Organization/${orgId}`,
148173
},
149174
POST: {
150175
LOGIN: '/identity/auth/login',
@@ -210,9 +235,11 @@ export const API_CONFIG = {
210235
`/post/${postId}/comment/${commentId}`,
211236
TOPUP: '/payment/topup',
212237
PURCHASE: '/payment/purchase',
238+
CREATE_ORGANIZATION: '/org/organization',
213239
},
214240
PUT: {
215241
EDIT_FILE: (id: string) => `/file/api/FileDocument/edit/${id}`,
242+
EDIT_ORG: (id: string) => `/org/api/Organization/${id}`,
216243
},
217244
PATCH: {
218245
UPDATE_EXERCISE: (exerciseId: string) =>
@@ -249,6 +276,7 @@ export const API_CONFIG = {
249276
DELETE_COMMENT_POST: (commentId: string) => `/post/comment/${commentId}`,
250277
UNSAVE_EXERCISE: (exerciseId: string) =>
251278
`/profile/exercise/${exerciseId}/save`,
279+
DELETE_ORG: (orgId: string) => `/org/organization/${orgId}`,
252280
},
253281
},
254282
HEADERS: {

src/app/features/auth/pages/oauth-callback/oauth-callback.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,10 @@ export class OauthCallbackComponent {
4444
localStorage.setItem('token', res.result.accessToken);
4545
localStorage.setItem('refreshToken', res.result.refreshToken);
4646

47-
if (!res.result.needPasswordSetup) {
48-
openModalNotification(
49-
this.store,
50-
'Cảnh báo',
51-
'Tài khoản của bạn chưa có mật khẩu, hãy cài đặt nó sớm nhất có thể để tránh rủi ro.',
52-
'Đồng ý',
53-
'hủy'
54-
);
55-
this.store.dispatch(
56-
setVariable({ key: 'needPasswordSetup', value: true })
57-
);
47+
if (res.result.needPasswordSetup) {
48+
localStorage.setItem('needPasswordSetup', 'true');
49+
} else {
50+
localStorage.setItem('needPasswordSetup', 'false');
5851
}
5952
} else {
6053
this.router.navigate(['/auth/identity/login']);

0 commit comments

Comments
 (0)