mirror of
https://github.com/Nezumi-2711/foodify-frontend.git
synced 2026-09-22 20:01:17 +00:00
Deployment 24.4
- Edit Category - Verify oobCode before reset pass - Change invoice -> account, delete account in User
This commit is contained in:
@@ -17,7 +17,7 @@ import { MenusModule } from './components/menus/menus.module';
|
||||
import { VendorsModule } from './components/vendors/vendors.module';
|
||||
import { UsersModule } from './components/users/users.module';
|
||||
import { LocalizationModule } from './components/localization/localization.module';
|
||||
import { InvoiceModule } from './components/invoice/invoice.module';
|
||||
import { AccountModule } from './components/account/account.module';
|
||||
import { SettingModule } from './components/setting/setting.module';
|
||||
import { ReportsModule } from './components/reports/reports.module';
|
||||
import { AuthModule } from './components/auth/auth.module';
|
||||
@@ -28,7 +28,6 @@ import { AngularFireModule } from "@angular/fire/compat";
|
||||
import { environment } from "../environments/environment";
|
||||
import { FirebaseService } from "./shared/service/firebase.service";
|
||||
import { AuthInterceptor } from "./shared/inceptor/auth-interceptor";
|
||||
import { NgImageSliderModule } from 'ng-image-slider'
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -39,7 +38,7 @@ import { NgImageSliderModule } from 'ng-image-slider'
|
||||
BrowserModule.withServerTransition({ appId: 'serverApp' }),
|
||||
AppRoutingModule,
|
||||
DashboardModule,
|
||||
InvoiceModule,
|
||||
AccountModule,
|
||||
SettingModule,
|
||||
ReportsModule,
|
||||
AuthModule,
|
||||
|
||||
+6
-4
@@ -1,15 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { InvoiceComponent } from './invoice.component';
|
||||
import { AccountComponent } from './account.component';
|
||||
import { AdminGuard } from 'src/app/shared/guard/admin-guard.service';
|
||||
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: InvoiceComponent,
|
||||
canActivate: [AdminGuard],
|
||||
component: AccountComponent,
|
||||
data: {
|
||||
title: "Invoice",
|
||||
breadcrumb: "Invoice"
|
||||
title: "Tài khoản",
|
||||
breadcrumb: "Danh sách"
|
||||
}
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,105 @@
|
||||
<!-- Container-fluid starts-->
|
||||
<div class="container-fluid">
|
||||
<div class="card">
|
||||
<!-- <div class="card-header">
|
||||
<h5>User Details</h5>
|
||||
</div> -->
|
||||
<div class="card-body">
|
||||
<div class="btn-popup pull-left">
|
||||
<input [(ngModel)]="searchName" (change)="searchUser()" class="form-control" type="text"
|
||||
placeholder="Tìm kiếm" />
|
||||
</div>
|
||||
<div id="batchDelete" class="category-table custom-datatable transcation-datatable user-image">
|
||||
<div class="table-responsive" *ngIf="users.length">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">Ảnh đại diện</th>
|
||||
<th scope="col"><a (click)="onSort('fullName')">Họ và tên</a></th>
|
||||
<th scope="col"><a (click)="onSort('email')">Email</a></th>
|
||||
<th scope="col"><a (click)="onSort('phoneNumber')">Số điện thoại</a></th>
|
||||
<th scope="col">Vai trò</th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let user of users; let i = index">
|
||||
<th>{{i + 1}}</th>
|
||||
<td scope="row">
|
||||
<img [src]="user.imageUrl" class="imgTable" style="width: 20px">
|
||||
</td>
|
||||
<td>
|
||||
{{user.fullName}}
|
||||
</td>
|
||||
<td>{{user.email}}</td>
|
||||
<td>{{user.phoneNumber}}</td>
|
||||
<td>
|
||||
<a *ngIf="user.role.roleName == 'ROLE_ADMIN'">Quản trị viên</a>
|
||||
<a *ngIf="user.role.roleName == 'ROLE_USER'">Người dùng</a>
|
||||
<a *ngIf="user.role.roleName == 'ROLE_SHOP'">Người bán hàng</a>
|
||||
<a *ngIf="user.role.roleName == 'ROLE_SHIPPER'">Shipper</a>
|
||||
</td>
|
||||
<td>
|
||||
<a style="cursor: pointer" href="javascript:void(0)"><i
|
||||
class='fa fa-edit f-12'></i></a>
|
||||
<a style="cursor: pointer" (click)="openModal(user, confirmDelete)"><i
|
||||
class="fa fa-trash-o"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Pagination -->
|
||||
<div class="d-flex justify-content-center p-2">
|
||||
<select [(ngModel)]="role" class="form-select" style="width: auto" name="pageSize"
|
||||
(change)="listAllUsers()">
|
||||
<option [selected]="true" [ngValue]="'ALL'">Tất cả</option>
|
||||
<option [ngValue]="'ROLE_ADMIN'">Quản trị viên</option>
|
||||
<option [value]="'ROLE_USER'" [ngValue]="'ROLE_USER'">Người dùng</option>
|
||||
<option [ngValue]="'ROLE_SHOP'">Người bán hàng</option>
|
||||
<option [ngValue]="'ROLE_SHIPPER'">Shipper</option>
|
||||
</select>
|
||||
|
||||
<ngb-pagination [(page)]="thePageNumber" [pageSize]="thePageSize"
|
||||
[collectionSize]="theTotalElements" [maxSize]="5" (pageChange)="listAllUsers()">
|
||||
</ngb-pagination>
|
||||
|
||||
<select [(ngModel)]="thePageSize" class="form-select" style="width: auto" name="pageSize"
|
||||
(change)="listAllUsers()">
|
||||
<option [value]="10" [selected]="true" [ngValue]="10">10 tài khoản / trang</option>
|
||||
<option [ngValue]="20">20 tài khoản / trang</option>
|
||||
<option [ngValue]="30">30 tài khoản / trang</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive" *ngIf="!users.length">
|
||||
<div class="d-flex justify-content-center p-2">
|
||||
<img src="../../../../assets/images/error/no-user.png" alt="">
|
||||
</div>
|
||||
<div class="d-flex justify-content-center p-2">
|
||||
<h4 style="color: #FF8084;">Không tìm thấy tài khoản</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Container-fluid Ends-->
|
||||
|
||||
<ng-template #confirmDelete>
|
||||
<div class="modal-body text-center">
|
||||
<h5 class="text-dark font-weight-bold mb-4">Bạn chắc chắn muốn xoá người dùng này ?</h5>
|
||||
<button type="button" class="btn btn-primary" (click)="confirmDeleted(deleteSuccess)">Tiếp
|
||||
tục</button>
|
||||
<button type="button" class="btn btn-secondary" (click)="closeLayer1()">Quay lại</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #deleteSuccess>
|
||||
<div class="modal-body text-center">
|
||||
<h5 class="text-dark font-weight-bold mb-4">Xoá người dùng thành công</h5>
|
||||
<button type="button" class="btn btn-primary" (click)="closeLayer1()">Tiếp tục</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,110 @@
|
||||
import { DecimalPipe } from '@angular/common';
|
||||
import { Component, OnInit, TemplateRef } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { TableService } from 'src/app/shared/service/table.service';
|
||||
import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
|
||||
import { User } from 'src/app/shared/tables/user';
|
||||
import { UserService } from 'src/app/shared/service/user.service';
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
import { FirebaseService } from 'src/app/shared/service/firebase.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-invoice',
|
||||
templateUrl: './account.component.html',
|
||||
styleUrls: ['./account.component.scss'],
|
||||
providers: [TableService, DecimalPipe]
|
||||
})
|
||||
export class AccountComponent implements OnInit {
|
||||
users: User[] = [];
|
||||
userDel: User
|
||||
|
||||
searchName: string = '';
|
||||
|
||||
//Pagination Properties
|
||||
role: string = 'ALL'
|
||||
thePageNumber = 1;
|
||||
thePageSize = 10;
|
||||
sortBy = 'id';
|
||||
sortDir = 'asc';
|
||||
theTotalElements = 0;
|
||||
|
||||
isSearch: boolean = false;
|
||||
|
||||
constructor(
|
||||
private userService: UserService,
|
||||
private formBuilder: FormBuilder,
|
||||
private firebaseService: FirebaseService,
|
||||
private modalService: BsModalService) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.listAllUsers()
|
||||
}
|
||||
|
||||
listAllUsers() {
|
||||
if (this.role != 'ALL') {
|
||||
this.userService.getAllUsersByRole(this.role, this.thePageNumber - 1, this.thePageSize, this.sortBy, this.sortDir).subscribe(this.processResult());
|
||||
}
|
||||
else {
|
||||
this.userService.getAllUsers(this.thePageNumber - 1, this.thePageSize, this.sortBy, this.sortDir).subscribe(this.processResult());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
searchUser() {
|
||||
if (this.searchName.trim() !== '') {
|
||||
if (this.role != 'ALL') {
|
||||
this.userService.getAllUsersByRoleAndEmailOrPhoneNumber(this.searchName, this.role, this.thePageNumber - 1, this.thePageSize, this.sortBy, this.sortDir).subscribe(this.processResult());
|
||||
}
|
||||
else {
|
||||
this.userService.getAllUsersByEmailOrPhoneNumber(this.searchName, this.thePageNumber - 1, this.thePageSize, this.sortBy, this.sortDir).subscribe(this.processResult());
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.listAllUsers();
|
||||
}
|
||||
}
|
||||
|
||||
processResult() {
|
||||
return (data: any) => {
|
||||
this.users = data.users;
|
||||
this.thePageNumber = data.page.pageNo + 1;
|
||||
this.thePageSize = data.page.pageSize;
|
||||
this.theTotalElements = data.page.totalElements;
|
||||
}
|
||||
}
|
||||
|
||||
onSort(sortItem: string) {
|
||||
if (this.sortDir == 'asc') {
|
||||
this.sortBy = sortItem;
|
||||
this.sortDir = 'desc';
|
||||
}
|
||||
else {
|
||||
this.sortDir = 'asc'
|
||||
}
|
||||
this.listAllUsers();
|
||||
}
|
||||
|
||||
//Modal
|
||||
layer1: BsModalRef;
|
||||
|
||||
openModal(user: User, template: TemplateRef<any>) {
|
||||
this.userDel = user;
|
||||
this.layer1 = this.modalService.show(template, { class: 'modal-sm' });
|
||||
}
|
||||
|
||||
confirmDeleted(success: TemplateRef<any>) {
|
||||
this.userService.deleteUserById(this.userDel.id).subscribe();
|
||||
this.firebaseService.deleteUserByEmail(this.userDel.email).subscribe(() => {
|
||||
this.listAllUsers();
|
||||
this.layer1.hide();
|
||||
this.layer1 = this.modalService.show(success, { class: 'modal-sm' });
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
closeLayer1() {
|
||||
this.layer1.hide();
|
||||
}
|
||||
}
|
||||
+7
-4
@@ -1,18 +1,21 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { InvoiceRoutingModule } from './invoice-routing.module';
|
||||
import { InvoiceComponent } from './invoice.component';
|
||||
import { InvoiceRoutingModule } from './account-routing.module';
|
||||
import { AccountComponent } from './account.component';
|
||||
import { SharedModule } from 'src/app/shared/shared.module';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
@NgModule({
|
||||
declarations: [InvoiceComponent],
|
||||
declarations: [AccountComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
InvoiceRoutingModule,
|
||||
FormsModule,
|
||||
SharedModule,
|
||||
ReactiveFormsModule,
|
||||
NgbModule
|
||||
]
|
||||
})
|
||||
export class InvoiceModule { }
|
||||
export class AccountModule { }
|
||||
@@ -4,6 +4,8 @@ import { FirebaseService } from "../../../shared/service/firebase.service";
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { Validation } from 'src/app/constants/Validation';
|
||||
import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
|
||||
import { AngularFireAuth } from '@angular/fire/compat/auth';
|
||||
import { error } from 'console';
|
||||
|
||||
@Component({
|
||||
selector: "app-reset-password",
|
||||
@@ -27,6 +29,7 @@ export class ResetPasswordComponent {
|
||||
private formBuilder: UntypedFormBuilder,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private firebaseService: FirebaseService,
|
||||
private firebaseAuth: AngularFireAuth,
|
||||
private modalService: BsModalService,
|
||||
private router: Router
|
||||
) {
|
||||
@@ -57,6 +60,13 @@ export class ResetPasswordComponent {
|
||||
//Get Token from link
|
||||
this.oobCode = this.activatedRoute.snapshot.queryParamMap.get('oobCode');
|
||||
this.action = this.activatedRoute.snapshot.queryParamMap.get('mode');
|
||||
this.resetPasswordForm = this.formBuilder.group({
|
||||
password: new FormControl("", [Validators.required, Validators.pattern(Validation.Regex.Password)]),
|
||||
confirmPassword: new FormControl("", [Validators.required, Validators.pattern(Validation.Regex.Password)]),
|
||||
},
|
||||
{
|
||||
validator: this.ConfirmedValidator("password", "confirmPassword"),
|
||||
})
|
||||
|
||||
if (this.action == 'verifyEmail') {
|
||||
this.firebaseService.confirmVerifyEmail(this.oobCode)
|
||||
@@ -64,13 +74,11 @@ export class ResetPasswordComponent {
|
||||
}
|
||||
|
||||
if (this.oobCode) {
|
||||
this.resetPasswordForm = this.formBuilder.group({
|
||||
password: new FormControl("", [Validators.required, Validators.pattern(Validation.Regex.Password)]),
|
||||
confirmPassword: new FormControl("", [Validators.required, Validators.pattern(Validation.Regex.Password)]),
|
||||
},
|
||||
{
|
||||
validator: this.ConfirmedValidator("password", "confirmPassword"),
|
||||
})
|
||||
this.firebaseAuth.checkActionCode(this.oobCode).then((info) => {
|
||||
|
||||
}).catch(error => {
|
||||
this.router.navigate(['/auth/forbidden']);
|
||||
})
|
||||
}
|
||||
else {
|
||||
this.router.navigate(['/auth/forbidden']);
|
||||
|
||||
@@ -176,8 +176,15 @@
|
||||
<ng-template #sendMailCompleted>
|
||||
<div class="modal-body text-center">
|
||||
<p>Đã gửi đường dẫn thay đổi mật khẩu đến email của bạn</p>
|
||||
<p>Vui lòng kiểm tra hòm thư</p>
|
||||
<button type="button" class="btn btn-primary" (click)="gmail()">Gmail</button>
|
||||
<button type="button" class="btn btn-secondary" (click)="closeLayer1()">Đóng</button>
|
||||
<p>Vui lòng kiểm tra hòm thư của bạn</p>
|
||||
<!-- <button type="button" class="btn btn-primary" (click)="gmail()">Gmail</button> -->
|
||||
<button type="button" class="btn btn-primary" (click)="closeLayer1()">Đóng</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #emailNotExisted>
|
||||
<div class="modal-body text-center">
|
||||
<p>Tài khoản này không tồn tại trong hệ thống. Vui lòng kiểm tra lại địa chỉ email</p>
|
||||
<button type="button" class="btn btn-primary" (click)="closeLayer1()">Đóng</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
@@ -4,6 +4,7 @@ import { FirebaseService } from "../../../shared/service/firebase.service";
|
||||
import { Router } from "@angular/router";
|
||||
import { Validation } from "src/app/constants/Validation";
|
||||
import { BsModalRef, BsModalService } from "ngx-bootstrap/modal";
|
||||
import { AuthService } from "src/app/shared/service/auth.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-send-email",
|
||||
@@ -19,10 +20,12 @@ export class SendEmailComponent {
|
||||
public active = 1;
|
||||
|
||||
@ViewChild('sendMailCompleted') sendMailCompleted: TemplateRef<any>
|
||||
@ViewChild('emailNotExisted') emailNotExisted: TemplateRef<any>
|
||||
|
||||
constructor(
|
||||
private formBuilder: UntypedFormBuilder,
|
||||
private firebaseService: FirebaseService,
|
||||
private authService: AuthService,
|
||||
private modalService: BsModalService,
|
||||
private router: Router
|
||||
) {
|
||||
@@ -62,8 +65,19 @@ export class SendEmailComponent {
|
||||
this.sendEmailForm.markAllAsTouched();
|
||||
return;
|
||||
}
|
||||
this.firebaseService.resetPassword(this.email.value);
|
||||
this.layer1 = this.modalService.show(this.sendMailCompleted, { class: "modal-sm" });
|
||||
|
||||
this.authService.checkEmailInDB(this.email.value).subscribe({
|
||||
next: (response) => {
|
||||
if (response.isTrue == true) {
|
||||
this.firebaseService.resetPassword(this.email.value);
|
||||
this.layer1 = this.modalService.show(this.sendMailCompleted, { class: "modal-sm" });
|
||||
}
|
||||
else {
|
||||
this.layer1 = this.modalService.show(this.emailNotExisted, { class: "modal-sm" })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
gmail() {
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
<!-- Container-fluid starts-->
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5>Invoice List</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="batchDelete" class="custom-datatable">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" sortable="no">No</th>
|
||||
<th scope="col" sortable="invoice">Invoice</th>
|
||||
<th scope="col" sortable="name" >Date</th>
|
||||
<th scope="col" sortable="name" >Shipping</th>
|
||||
<th scope="col" sortable="name" >Amount</th>
|
||||
<th scope="col" sortable="name" >Tax</th>
|
||||
<th scope="col" sortable="name" >Total</th>
|
||||
<th scope="col" sortable="name" >Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let item of tableItem$ | async ">
|
||||
<td scope="row">
|
||||
<span>{{item.no}}</span>
|
||||
</td>
|
||||
<td>
|
||||
{{item.invoice}}
|
||||
</td>
|
||||
<td>{{item.date}}</td>
|
||||
<td>{{item.shipping}}</td>
|
||||
<td>{{item.amount}}</td>
|
||||
<td>{{item.tax}}</td>
|
||||
<td>{{item.total}}</td>
|
||||
<td>
|
||||
<a href="javascript:void(0)"><i class='fa fa-edit f-12'></i></a>
|
||||
<a href="javascript:void(0)"><i class="fa fa-trash-o"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="d-flex justify-content-center p-2">
|
||||
<ngb-pagination
|
||||
[collectionSize]="(total$ | async)!" [(page)]="service.page" [pageSize]="service.pageSize">
|
||||
</ngb-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Container-fluid Ends-->
|
||||
@@ -1,45 +0,0 @@
|
||||
import { DecimalPipe } from '@angular/common';
|
||||
import { Component, OnInit, QueryList, ViewChildren } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { NgbdSortableHeader, SortEvent } from 'src/app/shared/directives/NgbdSortableHeader';
|
||||
import { TableService } from 'src/app/shared/service/table.service';
|
||||
import { InvoiceDB, INVOICEDB } from '../../shared/tables/invoice';
|
||||
|
||||
@Component({
|
||||
selector: 'app-invoice',
|
||||
templateUrl: './invoice.component.html',
|
||||
styleUrls: ['./invoice.component.scss'],
|
||||
providers: [TableService, DecimalPipe]
|
||||
})
|
||||
export class InvoiceComponent implements OnInit {
|
||||
|
||||
public tableItem$: Observable<InvoiceDB[]>;
|
||||
public searchText;
|
||||
total$: Observable<number>;
|
||||
|
||||
constructor(public service: TableService) {
|
||||
this.tableItem$ = service.tableItem$;
|
||||
this.total$ = service.total$;
|
||||
this.service.setUserData(INVOICEDB)
|
||||
}
|
||||
|
||||
@ViewChildren(NgbdSortableHeader) headers: QueryList<NgbdSortableHeader>;
|
||||
|
||||
onSort({ column, direction }: SortEvent) {
|
||||
// resetting other headers
|
||||
this.headers.forEach((header) => {
|
||||
if (header.sortable !== column) {
|
||||
header.direction = '';
|
||||
}
|
||||
});
|
||||
|
||||
this.service.sortColumn = column;
|
||||
this.service.sortDirection = direction;
|
||||
|
||||
}
|
||||
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="col-sm-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5>Product Lists</h5>
|
||||
<h5>Danh sách sản phẩm</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="batchDelete" class="custom-datatable">
|
||||
@@ -36,11 +36,12 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="d-flex justify-content-between p-2">
|
||||
<div class="d-flex justify-content-center p-2">
|
||||
<ngb-pagination [collectionSize]="theTotalElements" [(page)]="thePageNumber"
|
||||
[maxSize]="5" [pageSize]="thePageSize" [rotate]="true" [boundaryLinks]="true"
|
||||
(pageChange)="getProductByCategories()">
|
||||
</ngb-pagination>
|
||||
|
||||
<select class="form-select" style="width: auto" name="pageSize"
|
||||
(change)="getProductByCategories()" [(ngModel)]="thePageSize">
|
||||
<option [value]="10" [selected]="true" [ngValue]="10">10 sản phẩm / trang</option>
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ProductService } from 'src/app/shared/service/product.service';
|
||||
})
|
||||
export class CategoryDetailComponent implements OnInit {
|
||||
products = [];
|
||||
catName: string = '';
|
||||
categories: number[] = [];
|
||||
|
||||
//Pagination Properties
|
||||
@@ -28,7 +29,7 @@ export class CategoryDetailComponent implements OnInit {
|
||||
}
|
||||
|
||||
getProductByCategories() {
|
||||
const id = +this.route.snapshot.paramMap.get('id')
|
||||
const id = +this.route.snapshot.paramMap.get('id');
|
||||
this.categories.push(id)
|
||||
this.productService.getProductsByCategoryIds(this.categories, this.thePageNumber - 1, this.thePageSize).subscribe(
|
||||
this.processResult()
|
||||
@@ -41,6 +42,7 @@ export class CategoryDetailComponent implements OnInit {
|
||||
this.thePageNumber = data.page.pageNo + 1;
|
||||
this.thePageSize = data.page.pageSize;
|
||||
this.theTotalElements = data.page.totalElements;
|
||||
this.catName = this.products[0].categories.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,29 +7,15 @@
|
||||
<h5>Thể loại sản phẩm</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- <div class="btn-popup pull-right">-->
|
||||
<!-- <button-->
|
||||
<!-- type="button" class="btn btn-primary" data-toggle="modal" data-original-title="test"-->
|
||||
<!-- data-target="#exampleModal" (click)="open(content)">Add Category-->
|
||||
<!-- </button>-->
|
||||
|
||||
<!-- </div>-->
|
||||
<div id="batchDelete" class="category-table custom-datatable">
|
||||
<div class="table-responsive">
|
||||
<!-- <form>
|
||||
<div class="mb-3 row">
|
||||
<label for="table-complete-search" class="col-xs-3 col-sm-auto col-form-label">Full text search:</label>
|
||||
<div class="col-xs-3 col-sm-auto">
|
||||
<input id="table-complete-search" type="text" class="form-control" name="searchTerm" [(ngModel)]="searchText" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
</form> -->
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">STT</th>
|
||||
<th class="d-flex justify-content-center align-items-center" scope="col">
|
||||
<span>Ảnh</span></th>
|
||||
<span>Ảnh</span>
|
||||
</th>
|
||||
<th scope="col">Tên loại</th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
@@ -40,7 +26,8 @@
|
||||
<div>{{ i + 1 }}</div>
|
||||
</th>
|
||||
<td class="d-flex justify-content-center align-items-center ">
|
||||
<img [src]="category.imageUrl" class="imgTable" style="width: 20px"
|
||||
<img [src]="category.imageUrl" class="imgTable"
|
||||
style="width: 20px; cursor: pointer;"
|
||||
[routerLink]="['/products','category',category.id]">
|
||||
</td>
|
||||
<td>{{ category.name }}</td>
|
||||
@@ -48,8 +35,7 @@
|
||||
<a style="cursor: pointer;"
|
||||
[routerLink]="['/products','category',category.id]"><i
|
||||
style="color: lightseagreen;" class='fa fa-eye f-12'></i></a>
|
||||
<a style="cursor: pointer;"
|
||||
(click)="editCategory(productCategoryTemplate, category)"><i
|
||||
<a style="cursor: pointer;" (click)="editCategory(category)"><i
|
||||
class='fa fa-edit f-12'></i></a>
|
||||
<a style="cursor: pointer;"
|
||||
(click)="openModal(deleteCategory, category.id)"><i
|
||||
@@ -72,7 +58,7 @@
|
||||
<!-- Container-fluid Ends-->
|
||||
|
||||
<ng-template #productCategoryTemplate>
|
||||
<form formGroup="categoryForm">
|
||||
<form [formGroup]="categoryForm">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title f-w-600" id="exampleModalLabel">Edit Product Category</h5>
|
||||
<button type="button" class="close" aria-label="Close" (click)="decline()">
|
||||
@@ -83,13 +69,13 @@
|
||||
<div>
|
||||
<div class="form-group">
|
||||
<label for="validationCustom01" class="mb-1">Tên loại :</label>
|
||||
<input class="form-control" id="validationCustom01" type="text"
|
||||
[formControl]="categoryForm.controls['categoryName']" required>
|
||||
<input class="form-control" id="validationCustom01" type="text" formControlName="categoryName"
|
||||
required>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<label for="image" class="mb-1">Ảnh :</label>
|
||||
<input class="form-control" id="image" [formControl]="categoryForm.controls['categoryImage']"
|
||||
type="file" autocomplete="off" (change)="onFileSelected($event)">
|
||||
<input class="form-control" id="image" type="file" autocomplete="off"
|
||||
(change)="onFileSelected($event)">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, OnInit, TemplateRef } from '@angular/core';
|
||||
import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { DecimalPipe } from '@angular/common';
|
||||
import { TableService } from 'src/app/shared/service/table.service';
|
||||
import { CategoryService } from 'src/app/shared/service/category.service';
|
||||
@@ -7,7 +7,6 @@ import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { Category } from 'src/app/shared/tables/category';
|
||||
import { AngularFireStorage } from '@angular/fire/compat/storage';
|
||||
import { finalize, Observable } from 'rxjs';
|
||||
import { resolve } from 'path';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
@@ -24,11 +23,15 @@ export class CategoryComponent implements OnInit {
|
||||
categories: Category[];
|
||||
categoryId: number;
|
||||
|
||||
isChanged: boolean = false;
|
||||
|
||||
//File
|
||||
imageFile: File;
|
||||
imageUrl;
|
||||
downloadURL: Observable<string>;
|
||||
|
||||
@ViewChild('productCategoryTemplate') editCategoryModal: TemplateRef<any>
|
||||
|
||||
constructor(
|
||||
private categoryService: CategoryService,
|
||||
private modalService: BsModalService,
|
||||
@@ -36,8 +39,7 @@ export class CategoryComponent implements OnInit {
|
||||
private storage: AngularFireStorage,
|
||||
private router: Router) {
|
||||
this.categoryForm = this.formBuilder.group({
|
||||
categoryName: [''],
|
||||
categoryImage: ['']
|
||||
categoryName: ['']
|
||||
})
|
||||
}
|
||||
|
||||
@@ -71,19 +73,30 @@ export class CategoryComponent implements OnInit {
|
||||
this.modalRef.hide();
|
||||
}
|
||||
|
||||
editCategory(template: TemplateRef<any>, category: Category) {
|
||||
editCategory(category: Category) {
|
||||
this.categoryId = category.id
|
||||
this.imageUrl = category.imageUrl;
|
||||
|
||||
this.categoryForm.patchValue({
|
||||
categoryName: category.name,
|
||||
categoryImage: category.imageUrl
|
||||
categoryName: category?.name
|
||||
})
|
||||
|
||||
this.modalRef = this.modalService.show(template, { class: 'modal-md' });
|
||||
this.modalRef = this.modalService.show(this.editCategoryModal, { class: 'modal-md' });
|
||||
}
|
||||
|
||||
onSaveCategory(event, template: TemplateRef<any>) {
|
||||
this.uploadImage().then(() => {
|
||||
if (this.isChanged == true) {
|
||||
this.uploadImage().then(() => {
|
||||
const category = new Category()
|
||||
category.name = this.categoryName
|
||||
category.imageUrl = this.imageUrl;
|
||||
|
||||
this.categoryService.editCategoryById(this.categoryId, category).subscribe()
|
||||
this.modalRef.hide();
|
||||
this.modalRef = this.modalService.show(template, { class: 'modal-md' });
|
||||
})
|
||||
}
|
||||
else {
|
||||
const category = new Category()
|
||||
category.name = this.categoryName
|
||||
category.imageUrl = this.imageUrl;
|
||||
@@ -91,7 +104,8 @@ export class CategoryComponent implements OnInit {
|
||||
this.categoryService.editCategoryById(this.categoryId, category).subscribe()
|
||||
this.modalRef.hide();
|
||||
this.modalRef = this.modalService.show(template, { class: 'modal-md' });
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
success(): void {
|
||||
@@ -101,6 +115,7 @@ export class CategoryComponent implements OnInit {
|
||||
}
|
||||
|
||||
onFileSelected(event) {
|
||||
this.isChanged = true;
|
||||
this.imageFile = event.target.files[0];
|
||||
}
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@
|
||||
<label for="validationCustom03" class="mb-0">Id shop</label>
|
||||
</div>
|
||||
<div class="col-xl-8 col-sm-7">
|
||||
<input class="form-control" id="validationCustom03"
|
||||
<input readonly class="form-control" id="validationCustom03"
|
||||
[formControl]="editProductForm.controls['shopId']">
|
||||
<div *ngIf="productShopId?.invalid && (productShopId?.dirty || productShopId?.touched)"
|
||||
class="alert alert-danger mt-1">
|
||||
|
||||
@@ -39,8 +39,8 @@ const routes: Routes = [
|
||||
canActivate: [AdminGuard],
|
||||
component: CategoryDetailComponent,
|
||||
data: {
|
||||
title: "Danh sách sản phẩm",
|
||||
breadcrumb: "Thể loại"
|
||||
title: "Chi tiết thể loại",
|
||||
breadcrumb: "Chi tiết"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -22,7 +22,6 @@ import { ListAccountComponent } from './list-account/list-account.component';
|
||||
SharedModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
ReactiveFormsModule,
|
||||
UsersRoutingModule
|
||||
]
|
||||
})
|
||||
|
||||
@@ -84,8 +84,8 @@ export const content: Routes = [
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'invoice',
|
||||
loadChildren: () => import('../../components/invoice/invoice.module').then(m => m.InvoiceModule),
|
||||
path: 'account',
|
||||
loadChildren: () => import('../../components/account/account.module').then(m => m.AccountModule),
|
||||
data: {
|
||||
breadcrumb: "Hoá đơn"
|
||||
}
|
||||
|
||||
@@ -35,4 +35,8 @@ export class AuthService {
|
||||
checkEmailOrPhoneNumberExist(userDto: User) {
|
||||
return this.httpClient.post<StringBoolObject>(this.baseUrl + `/check`, userDto);
|
||||
}
|
||||
|
||||
checkEmailInDB(email: string) {
|
||||
return this.httpClient.get<StringBoolObject>(this.baseUrl + `/check-email?email=${email}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,11 +112,13 @@ export class NavService {
|
||||
// { path: '/menus/create-menu', title: 'Create Menu', type: 'link' },
|
||||
// ]
|
||||
// },
|
||||
{
|
||||
title: 'Tài khoản', path: '/account', icon: 'user', type: 'link', active: false
|
||||
},
|
||||
{
|
||||
title: 'Người dùng', icon: 'user-plus', type: 'sub', active: false, children: [
|
||||
{ path: '/users/list', title: 'Danh sách', type: 'link' },
|
||||
{ path: '/users/create', title: 'Tạo người dùng', type: 'link' },
|
||||
{ path: '/users/accounts/list', title: 'Tài khoản', type: 'link' },
|
||||
{ path: '/users/create', title: 'Tạo người dùng', type: 'link' }
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -136,7 +138,7 @@ export class NavService {
|
||||
{ path: '/utilities/list-address', title: 'Địa chỉ', type: 'link' },
|
||||
{ path: '/utilities/list-slider', title: 'Slider', type: 'link' }
|
||||
]
|
||||
}
|
||||
},
|
||||
// {
|
||||
// title: 'Localization', icon: 'chrome', type: 'sub', children: [
|
||||
// {path: '/localization/translations', title: 'Translations', type: 'link'},
|
||||
@@ -148,9 +150,6 @@ export class NavService {
|
||||
// title: 'Báo cáo', path: '/reports', icon: 'bar-chart', type: 'link', active: false
|
||||
// },
|
||||
// {
|
||||
// title: 'Hoá đơn', path: '/invoice', icon: 'archive', type: 'link', active: false
|
||||
// },
|
||||
// {
|
||||
// title: 'Cài đặt', icon: 'settings', type: 'sub', children: [
|
||||
// { path: '/settings/profile', title: 'Trang cá nhân', type: 'link' },
|
||||
// ]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
export const environment = {
|
||||
production: false,
|
||||
// foodOrderingBaseApiUrl: 'http://localhost:8080/api',
|
||||
foodOrderingBaseApiUrl: 'https://foodify-backend-production.up.railway.app/api',
|
||||
firebaseConfig: {
|
||||
apiKey: 'AIzaSyAZFFIuXkbgdp2F-Em4CK2z8kVJ2L4p_UU',
|
||||
|
||||
Reference in New Issue
Block a user