Skip to content

Commit 1ab1c7b

Browse files
authored
Merge pull request #175 from CapstoneProjectCMC/feature/sap-service-and-payment
fix some bug
2 parents 3113531 + 5f05a89 commit 1ab1c7b

File tree

21 files changed

+1342
-343
lines changed

21 files changed

+1342
-343
lines changed

src/app/core/interceptors/handle/error-handler.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class ErrorHandlerService {
4545
sendNotification(
4646
this.store,
4747
'Hết tiền!',
48-
'Bạn cần nạp tiền vào tài khoản của mình trước nhé!',
48+
'Bạn cần nạp tiền vào tài khoản của mình trước để kích hoạt ví nhé!',
4949
'error'
5050
);
5151
} else {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export type ReadStatusNotice = 'ALL' | 'READ' | 'UNREAD';
2+
3+
export type DeliveryStatus = 'PENDING' | 'SENT' | 'FAILED';
4+
5+
export type GetAllNoticeResponse = {
6+
id: string;
7+
recipient: string;
8+
channel: ReadStatusNotice; // "SOCKET" | "EMAIL" | "ALL"...
9+
templateCode: string;
10+
subject: string;
11+
body: string;
12+
param: { class: string; exercise: string };
13+
readStatus: string;
14+
readAt: null;
15+
deliveryStatus: DeliveryStatus; //// PENDING | SENT | FAILED
16+
deliveredAt: string;
17+
createdAt: string;
18+
};

src/app/core/models/user.models.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,20 @@ export type RequestForgotPasswordResponse = {
7777
email: string;
7878
message: string;
7979
};
80+
81+
export type CreateAccoutByAdmin = {
82+
username: string;
83+
email: string;
84+
password: string;
85+
firstName: string;
86+
lastName: string;
87+
dob: string;
88+
bio: string;
89+
gender: boolean;
90+
displayName: string;
91+
education: number;
92+
links: string[];
93+
city: string;
94+
organizationId: string;
95+
organizationMemberRole: 'ADMIN' | 'TEACHER' | 'STUDENT';
96+
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { Injectable } from '@angular/core';
2+
3+
import { ApiMethod } from '../config-service/api.methods';
4+
import { ApiResponse, IPaginationResponse } from '../../models/api-response';
5+
import { API_CONFIG } from '../config-service/api.enpoints';
6+
import {
7+
GetAllNoticeResponse,
8+
ReadStatusNotice,
9+
} from '../../models/notice.model';
10+
11+
@Injectable({
12+
providedIn: 'root',
13+
})
14+
export class NotificationListService {
15+
constructor(private api: ApiMethod) {}
16+
getAllMyNotification(
17+
page: number,
18+
size: number,
19+
statusRead: ReadStatusNotice
20+
) {
21+
return this.api.get<
22+
ApiResponse<IPaginationResponse<GetAllNoticeResponse[]>>
23+
>(
24+
API_CONFIG.ENDPOINTS.GET.GET_ALL_MY_NOTIFICATIONS(page, size, statusRead)
25+
);
26+
}
27+
28+
markAsReadNotification(Ids: string[]) {
29+
return this.api.post<ApiResponse<null>>(
30+
API_CONFIG.ENDPOINTS.POST.MARK_AS_READ_NOTIFICATION,
31+
Ids
32+
);
33+
}
34+
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ApiMethod } from '../config-service/api.methods';
33
import { EnumType } from '../../models/data-handle';
44
import { ApiResponse, IPaginationResponse } from '../../models/api-response';
55
import {
6+
CreateAccoutByAdmin,
67
SearchingUser,
78
SearchUserProfileResponse,
89
User,
@@ -45,4 +46,21 @@ export class UserService {
4546
{}
4647
);
4748
}
49+
50+
createAccountUser(
51+
role: 'ADMIN' | 'STUDENT' | 'TEACHER',
52+
data: CreateAccoutByAdmin
53+
) {
54+
let enpoint = '';
55+
56+
if (role === 'ADMIN') {
57+
enpoint = API_CONFIG.ENDPOINTS.POST.ADD_ADMIN;
58+
} else if (role === 'STUDENT') {
59+
enpoint = API_CONFIG.ENDPOINTS.POST.ADD_STUDENT;
60+
} else if (role === 'TEACHER') {
61+
enpoint = API_CONFIG.ENDPOINTS.POST.ADD_TEACHER;
62+
}
63+
64+
return this.api.post<ApiResponse<null>>(enpoint, data);
65+
}
4866
}

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

Lines changed: 12 additions & 1 deletion
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 { ReadStatusNotice } from '../../models/notice.model';
34
import {
45
FilterOrgs,
56
ParamGetAllBlockOfOrg,
@@ -200,12 +201,18 @@ export const API_CONFIG = {
200201
data: { membersPage: number; membersSize: number; activeOnly: boolean }
201202
) =>
202203
`/org/block/${blockId}?membersPage=${data.membersPage}&membersSize=${data.membersSize}&activeOnly=${data.activeOnly}`,
204+
GET_ALL_MY_NOTIFICATIONS: (
205+
page: number,
206+
size: number,
207+
readStatus: ReadStatusNotice
208+
) =>
209+
`/notification/my?page=${page}&size=${size}&readStatus=${readStatus}`,
203210
},
204211
POST: {
205212
LOGIN: '/identity/auth/login',
206213
REGISTER: '/identity/auth/register',
207214
LOGOUT: '/identity/auth/logout',
208-
CREATE_FIRST_PASSWORD: '/identity/auth/user/create-password',
215+
CREATE_FIRST_PASSWORD: '/identity/user/create-password',
209216
REQUEST_FORGOT_PASSWORD: '/identity/auth/forgot-password/request',
210217
RESET_PASSWORD: `/identity/auth/forgot-password/reset`,
211218
REFRESH_TOKEN: '/identity/auth/refresh',
@@ -271,6 +278,10 @@ export const API_CONFIG = {
271278
BULK_ADD_TO_BLOCK: (blockId: string) =>
272279
`/org/block/${blockId}/members:bulk`,
273280
IMPORT_EXCEL_ADD_MEMBER: '/identity/users/import',
281+
ADD_ADMIN: '/identity/admin',
282+
ADD_STUDENT: '/identity/teacher',
283+
ADD_TEACHER: '/identity/user',
284+
MARK_AS_READ_NOTIFICATION: '/my/mark-read',
274285
},
275286
PUT: {
276287
EDIT_FILE: (id: string) => `/file/api/FileDocument/edit/${id}`,
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
<div class="modal-overlay" [class.active]="isOpen" (click)="closeModal()">
2+
<div
3+
class="modal-content"
4+
[class.active]="isOpen"
5+
(click)="$event.stopPropagation()"
6+
>
7+
<div class="modal-header">
8+
<h2>Tạo người dùng mới</h2>
9+
<button class="close-btn" (click)="closeModal()">&times;</button>
10+
</div>
11+
12+
<div class="modal-body">
13+
<form [formGroup]="createUserForm" (ngSubmit)="onSubmit()">
14+
<div class="steps-container">
15+
<!-- STEP 1 -->
16+
<div class="form-step" [class.active]="currentStep === 1">
17+
<div class="form-group">
18+
<label>Vai trò hệ thống *</label>
19+
<select formControlName="role">
20+
<option value="STUDENT">Học sinh</option>
21+
<option value="TEACHER">Giáo viên</option>
22+
<option value="ADMIN">Quản trị viên</option>
23+
</select>
24+
</div>
25+
26+
<div class="form-group">
27+
<label>Giới tính *</label>
28+
<select formControlName="gender">
29+
<option [ngValue]="true">Nam</option>
30+
<option [ngValue]="false">Nữ</option>
31+
</select>
32+
</div>
33+
34+
<div class="form-grid-2">
35+
<div class="form-group">
36+
<label for="firstName">Họ *</label>
37+
<input type="text" id="firstName" formControlName="firstName" />
38+
</div>
39+
<div class="form-group">
40+
<label for="lastName">Tên *</label>
41+
<input type="text" id="lastName" formControlName="lastName" />
42+
</div>
43+
</div>
44+
45+
<div class="form-group">
46+
<label for="username">User Name *</label>
47+
<input type="text" id="username" formControlName="username" />
48+
</div>
49+
50+
<div class="form-group">
51+
<label for="email">Email *</label>
52+
<input type="email" id="email" formControlName="email" />
53+
</div>
54+
55+
<div class="form-group">
56+
<label for="password">Mật khẩu *</label>
57+
<input type="password" id="password" formControlName="password" />
58+
</div>
59+
60+
<div class="form-group">
61+
<label for="displayName">Tên hiển thị *</label>
62+
<input
63+
type="text"
64+
id="displayName"
65+
formControlName="displayName"
66+
/>
67+
</div>
68+
69+
<!-- Ngày sinh -->
70+
<div class="form-group">
71+
<label for="dob">Ngày sinh *</label>
72+
<input type="date" id="dob" formControlName="dob" />
73+
</div>
74+
</div>
75+
76+
<!-- STEP 2 -->
77+
<div class="form-step" [class.active]="currentStep === 2">
78+
<div class="form-group">
79+
<label for="bio">Tiểu sử</label>
80+
<textarea id="bio" rows="3" formControlName="bio"></textarea>
81+
</div>
82+
83+
<div class="form-group">
84+
<label for="education">Trình độ học vấn</label>
85+
<select id="education" formControlName="education">
86+
<option
87+
*ngFor="let option of educationOptions"
88+
[value]="option.value"
89+
>
90+
{{ option.label }}
91+
</option>
92+
</select>
93+
</div>
94+
95+
<div class="form-group">
96+
<label for="links">Liên kết cá nhân</label>
97+
<input
98+
type="text"
99+
id="links"
100+
formControlName="links"
101+
placeholder="https://..."
102+
/>
103+
</div>
104+
105+
<div class="form-group">
106+
<label for="city">Thành phố</label>
107+
<input type="text" id="city" formControlName="city" />
108+
</div>
109+
110+
<div class="form-group org-search-group">
111+
<label for="organization">Tổ chức *</label>
112+
<input
113+
type="text"
114+
id="organization"
115+
placeholder="Tìm kiếm theo tên tổ chức..."
116+
[value]="selectedOrganizationName || ''"
117+
(input)="onOrgSearchInput($event)"
118+
(focus)="showOrgDropdown = true"
119+
/>
120+
121+
<div class="org-dropdown" *ngIf="showOrgDropdown">
122+
<div *ngIf="isSearchingOrgs" class="dropdown-item loading">
123+
Đang tìm...
124+
</div>
125+
<div
126+
*ngIf="!isSearchingOrgs && searchedOrganizations.length === 0"
127+
class="dropdown-item not-found"
128+
>
129+
Không tìm thấy kết quả.
130+
</div>
131+
<div
132+
*ngFor="let org of searchedOrganizations"
133+
class="dropdown-item"
134+
(click)="selectOrganization(org)"
135+
>
136+
{{ org.name }}
137+
</div>
138+
</div>
139+
</div>
140+
141+
<div class="form-group">
142+
<label>Vai trò trong tổ chức *</label>
143+
<select formControlName="organizationMemberRole">
144+
<option value="STUDENT">Học sinh</option>
145+
<option value="TEACHER">Giáo viên</option>
146+
<option value="ADMIN">Quản trị viên</option>
147+
</select>
148+
</div>
149+
</div>
150+
</div>
151+
</form>
152+
</div>
153+
154+
<div class="modal-footer">
155+
<button
156+
class="btn btn-secondary"
157+
*ngIf="currentStep === 2"
158+
(click)="prevStep()"
159+
>
160+
Quay lại
161+
</button>
162+
163+
<button
164+
class="btn btn-primary"
165+
*ngIf="currentStep === 1"
166+
(click)="nextStep()"
167+
>
168+
Tiếp theo
169+
</button>
170+
171+
<button
172+
class="btn btn-primary"
173+
*ngIf="currentStep === 2"
174+
[disabled]="isSubmitting"
175+
(click)="onSubmit()"
176+
>
177+
<span *ngIf="!isSubmitting">Tạo người dùng</span>
178+
<span *ngIf="isSubmitting" class="spinner"></span>
179+
</button>
180+
</div>
181+
</div>
182+
</div>

0 commit comments

Comments
 (0)