From be39026b6ae56d2019b00763e4249febc623c70a Mon Sep 17 00:00:00 2001 From: JUNG YI DAM Date: Tue, 12 Jul 2022 06:05:24 +0000 Subject: [PATCH 1/8] =?UTF-8?q?=EC=A0=84=EC=B2=B4=ED=8C=8C=ED=8A=B8?= =?UTF-8?q?=EB=84=88=20page=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.routing.ts | 7 + .../apps/member/partner/partner-api.ts | 217 ++++++++++ .../apps/member/partner/partner-data.ts | 30 ++ src/app/mock-api/common/navigation/data.ts | 7 + src/app/mock-api/index.ts | 2 + .../member/casinomoney/casinomoney.routing.ts | 2 +- .../admin/member/partner/components/index.ts | 3 + .../partner/components/list.component.html | 374 ++++++++++++++++++ .../partner/components/list.component.ts | 198 ++++++++++ .../partner/models/partner-pagination.ts | 8 + .../admin/member/partner/models/partner.ts | 31 ++ .../admin/member/partner/partner.module.ts | 48 +++ .../admin/member/partner/partner.routing.ts | 24 ++ .../partner/resolvers/partner.resolver.ts | 89 +++++ .../partner/services/partner.service.ts | 153 +++++++ src/assets/i18n/en.json | 3 +- src/assets/i18n/ko.json | 2 +- 17 files changed, 1195 insertions(+), 3 deletions(-) create mode 100644 src/app/mock-api/apps/member/partner/partner-api.ts create mode 100644 src/app/mock-api/apps/member/partner/partner-data.ts create mode 100644 src/app/modules/admin/member/partner/components/index.ts create mode 100644 src/app/modules/admin/member/partner/components/list.component.html create mode 100644 src/app/modules/admin/member/partner/components/list.component.ts create mode 100644 src/app/modules/admin/member/partner/models/partner-pagination.ts create mode 100644 src/app/modules/admin/member/partner/models/partner.ts create mode 100644 src/app/modules/admin/member/partner/partner.module.ts create mode 100644 src/app/modules/admin/member/partner/partner.routing.ts create mode 100644 src/app/modules/admin/member/partner/resolvers/partner.resolver.ts create mode 100644 src/app/modules/admin/member/partner/services/partner.service.ts diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts index 7c0dd24..ef10a55 100644 --- a/src/app/app.routing.ts +++ b/src/app/app.routing.ts @@ -171,6 +171,13 @@ export const appRoutes: Route[] = [ 'app/modules/admin/member/current-user/current-user.module' ).then((m: any) => m.CurrentUserModule), }, + { + path: 'partner', + loadChildren: () => + import('app/modules/admin/member/partner/partner.module').then( + (m: any) => m.PartnerModule + ), + }, ], }, { diff --git a/src/app/mock-api/apps/member/partner/partner-api.ts b/src/app/mock-api/apps/member/partner/partner-api.ts new file mode 100644 index 0000000..b94ffa5 --- /dev/null +++ b/src/app/mock-api/apps/member/partner/partner-api.ts @@ -0,0 +1,217 @@ +import { Injectable } from '@angular/core'; +import { assign, cloneDeep } from 'lodash-es'; +import { FuseMockApiService, FuseMockApiUtils } from '@fuse/lib/mock-api'; +import { partners as partnersData } from './partner-data'; + +@Injectable({ + providedIn: 'root', +}) +export class MemberPartnerMockApi { + private _partners: any[] = partnersData; + + /** + * Constructor + */ + constructor(private _fuseMockApiService: FuseMockApiService) { + // Register Mock API handlers + this.registerHandlers(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Register Mock API handlers + */ + registerHandlers(): void { + // ----------------------------------------------------------------------------------------------------- + // @ Partners - GET + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onGet('api/apps/member/partner/partners', 300) + .reply(({ request }) => { + // Get available queries + const search = request.params.get('search'); + const sort = request.params.get('sort') || 'name'; + const order = request.params.get('order') || 'asc'; + const page = parseInt(request.params.get('page') ?? '1', 10); + const size = parseInt(request.params.get('size') ?? '10', 10); + + // Clone the partners + let partners: any[] | null = cloneDeep(this._partners); + + // Sort the partners + if (sort === 'sku' || sort === 'name' || sort === 'active') { + partners.sort((a, b) => { + const fieldA = a[sort].toString().toUpperCase(); + const fieldB = b[sort].toString().toUpperCase(); + return order === 'asc' + ? fieldA.localeCompare(fieldB) + : fieldB.localeCompare(fieldA); + }); + } else { + partners.sort((a, b) => + order === 'asc' ? a[sort] - b[sort] : b[sort] - a[sort] + ); + } + + // If search exists... + if (search) { + // Filter the partners + partners = partners.filter( + (contact: any) => + contact.name && + contact.name.toLowerCase().includes(search.toLowerCase()) + ); + } + + // Paginate - Start + const partnersLength = partners.length; + + // Calculate pagination details + const begin = page * size; + const end = Math.min(size * (page + 1), partnersLength); + const lastPage = Math.max(Math.ceil(partnersLength / size), 1); + + // Prepare the pagination object + let pagination = {}; + + // If the requested page number is bigger than + // the last possible page number, return null for + // partners but also send the last possible page so + // the app can navigate to there + if (page > lastPage) { + partners = null; + pagination = { + lastPage, + }; + } else { + // Paginate the results by size + partners = partners.slice(begin, end); + + // Prepare the pagination mock-api + pagination = { + length: partnersLength, + size: size, + page: page, + lastPage: lastPage, + startIndex: begin, + endIndex: end - 1, + }; + } + + // Return the response + return [ + 200, + { + partners, + pagination, + }, + ]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ Partner - GET + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onGet('api/apps/member/partner/partner') + .reply(({ request }) => { + // Get the id from the params + const id = request.params.get('id'); + + // Clone the partners + const partners = cloneDeep(this._partners); + + // Find the partner + const partner = partners.find((item: any) => item.id === id); + + // Return the response + return [200, partner]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ Partner - POST + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onPost('api/apps/member/partner/partner') + .reply(() => { + // Generate a new partner + const newPartner = { + id: FuseMockApiUtils.guid(), + category: '', + name: 'A New User', + description: '', + tags: [], + sku: '', + barcode: '', + brand: '', + vendor: '', + stock: '', + reserved: '', + cost: '', + basePrice: '', + taxPercent: '', + price: '', + weight: '', + thumbnail: '', + images: [], + active: false, + }; + + // Unshift the new partner + this._partners.unshift(newPartner); + + // Return the response + return [200, newPartner]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ Partner - PATCH + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onPatch('api/apps/member/partner/partner') + .reply(({ request }) => { + // Get the id and partner + const id = request.body.id; + const partner = cloneDeep(request.body.partner); + + // Prepare the updated partner + let updatedPartner = null; + + // Find the partner and update it + this._partners.forEach((item, index, partners) => { + if (item.id === id) { + // Update the partner + partners[index] = assign({}, partners[index], partner); + + // Store the updated partner + updatedPartner = partners[index]; + } + }); + + // Return the response + return [200, updatedPartner]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ Partner - DELETE + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onDelete('api/apps/member/partner/partner') + .reply(({ request }) => { + // Get the id + const id = request.params.get('id'); + + // Find the partner and delete it + this._partners.forEach((item, index) => { + if (item.id === id) { + this._partners.splice(index, 1); + } + }); + + // Return the response + return [200, true]; + }); + } +} diff --git a/src/app/mock-api/apps/member/partner/partner-data.ts b/src/app/mock-api/apps/member/partner/partner-data.ts new file mode 100644 index 0000000..66280ff --- /dev/null +++ b/src/app/mock-api/apps/member/partner/partner-data.ts @@ -0,0 +1,30 @@ +/* eslint-disable */ + +export const partners = [ + { + id: 'kgon1', + nickname: '본사', + rank: '본사', + branchCount: 2, + divisionCount: 2, + officeCount: 1, + storeCount: 1, + memberCount: 5, + level: '1', + calculateType: '롤링', + holdingMoney: 253675, + accountHolder: '본사', + phoneNumber: '010-0000-0000', + comp: 100737, + coupon: 1900000, + ownCharge: 460000, + bottomCharge: 54020000, + ownExchange: 100000, + bottomExchange: 19970000, + ownRevenue: 360000, + bottomRevenue: 34050000, + accession: '2021-10-14 10:53', + state: '정상', + note: '대본등록', + }, +]; diff --git a/src/app/mock-api/common/navigation/data.ts b/src/app/mock-api/common/navigation/data.ts index 93e8827..b7399fd 100644 --- a/src/app/mock-api/common/navigation/data.ts +++ b/src/app/mock-api/common/navigation/data.ts @@ -67,6 +67,13 @@ export const defaultNavigation: FuseNavigationItem[] = [ icon: 'heroicons_outline:academic-cap', link: '/member/current-user', }, + { + id: 'member.partner', + title: 'All Partner', + type: 'basic', + icon: 'heroicons_outline:academic-cap', + link: '/member/partner', + }, ], }, { diff --git a/src/app/mock-api/index.ts b/src/app/mock-api/index.ts index 9cf809e..365f7b9 100644 --- a/src/app/mock-api/index.ts +++ b/src/app/mock-api/index.ts @@ -15,6 +15,7 @@ import { MemberUserMockApi } from 'app/mock-api/apps/member/user/api'; import { MemberCasinomoneyMockApi } from './apps/member/casinomoney/api'; import { MemberUnconnectedMockApi } from './apps/member/unconnected/api'; import { MemberCurrentUserMockApi } from './apps/member/current-user/api'; +import { MemberPartnerMockApi } from './apps/member/partner/partner-api'; import { MessagesMockApi } from 'app/mock-api/common/messages/api'; import { NavigationMockApi } from 'app/mock-api/common/navigation/api'; import { NotesMockApi } from 'app/mock-api/apps/notes/api'; @@ -50,6 +51,7 @@ export const mockApiServices = [ MemberCasinomoneyMockApi, MemberUnconnectedMockApi, MemberCurrentUserMockApi, + MemberPartnerMockApi, MessagesMockApi, NavigationMockApi, NotesMockApi, diff --git a/src/app/modules/admin/member/casinomoney/casinomoney.routing.ts b/src/app/modules/admin/member/casinomoney/casinomoney.routing.ts index 500956f..7ee1be0 100644 --- a/src/app/modules/admin/member/casinomoney/casinomoney.routing.ts +++ b/src/app/modules/admin/member/casinomoney/casinomoney.routing.ts @@ -11,7 +11,7 @@ export const casinomoneyRoutes: Route[] = [ path: '', component: ListComponent, resolve: { - casinomoneyrs: CasinomoneysResolver, + casinomoneys: CasinomoneysResolver, }, }, { diff --git a/src/app/modules/admin/member/partner/components/index.ts b/src/app/modules/admin/member/partner/components/index.ts new file mode 100644 index 0000000..04759eb --- /dev/null +++ b/src/app/modules/admin/member/partner/components/index.ts @@ -0,0 +1,3 @@ +import { ListComponent } from './list.component'; + +export const COMPONENTS = [ListComponent]; diff --git a/src/app/modules/admin/member/partner/components/list.component.html b/src/app/modules/admin/member/partner/components/list.component.html new file mode 100644 index 0000000..380355d --- /dev/null +++ b/src/app/modules/admin/member/partner/components/list.component.html @@ -0,0 +1,374 @@ +
+ +
+ +
+ +
+ +
전체목록
+ +
+ + + + + + + + + + +
+
+ + +
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + {{ partner.rank }} + + + {{ partner.nickname }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + +
+
+ + +
+ There are no partners! +
+
+
+
+
diff --git a/src/app/modules/admin/member/partner/components/list.component.ts b/src/app/modules/admin/member/partner/components/list.component.ts new file mode 100644 index 0000000..ff0e586 --- /dev/null +++ b/src/app/modules/admin/member/partner/components/list.component.ts @@ -0,0 +1,198 @@ +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + OnDestroy, + OnInit, + ViewChild, + ViewEncapsulation, +} from '@angular/core'; +import { + FormBuilder, + FormControl, + FormGroup, + Validators, +} from '@angular/forms'; +import { MatCheckboxChange } from '@angular/material/checkbox'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { + debounceTime, + map, + merge, + Observable, + Subject, + switchMap, + takeUntil, +} from 'rxjs'; +import { fuseAnimations } from '@fuse/animations'; +import { FuseConfirmationService } from '@fuse/services/confirmation'; + +import { User } from '../../user/models/user'; +import { Partner } from '../models/partner'; +import { PartnerPagination } from '../models/partner-pagination'; +import { PartnerService } from '../services/partner.service'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'list', + templateUrl: './list.component.html', + styles: [ + /* language=SCSS */ + ` + .inventory-grid { + grid-template-columns: 60px auto 40px; + + @screen sm { + grid-template-columns: 60px auto 60px 72px; + } + + @screen md { + grid-template-columns: 60px 60px auto 112px 72px; + } + + @screen lg { + grid-template-columns: 60px 60px auto 112px 96px 96px 72px; + } + } + `, + ], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush, + animations: fuseAnimations, +}) +export class ListComponent implements OnInit, AfterViewInit, OnDestroy { + @ViewChild(MatPaginator) private _paginator!: MatPaginator; + @ViewChild(MatSort) private _sort!: MatSort; + + partners$!: Observable; + users$!: Observable; + + isLoading = false; + searchInputControl = new FormControl(); + selectedPartner?: Partner; + pagination?: PartnerPagination; + + private _unsubscribeAll: Subject = new Subject(); + + /** + * Constructor + */ + constructor( + private _changeDetectorRef: ChangeDetectorRef, + private _fuseConfirmationService: FuseConfirmationService, + private _formBuilder: FormBuilder, + private _partnerService: PartnerService, + private router: Router + ) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Lifecycle hooks + // ----------------------------------------------------------------------------------------------------- + + /** + * On init + */ + ngOnInit(): void { + // Get the pagination + this._partnerService.pagination$ + .pipe(takeUntil(this._unsubscribeAll)) + .subscribe((pagination: PartnerPagination | undefined) => { + // Update the pagination + this.pagination = pagination; + + // Mark for check + this._changeDetectorRef.markForCheck(); + }); + + // Get the products + this.partners$ = this._partnerService.partners$; + } + + /** + * After view init + */ + ngAfterViewInit(): void { + if (this._sort && this._paginator) { + // Set the initial sort + this._sort.sort({ + id: 'name', + start: 'asc', + disableClear: true, + }); + + // Mark for check + this._changeDetectorRef.markForCheck(); + + // If the partner changes the sort order... + this._sort.sortChange + .pipe(takeUntil(this._unsubscribeAll)) + .subscribe(() => { + // Reset back to the first page + this._paginator.pageIndex = 0; + }); + + // Get products if sort or page changes + merge(this._sort.sortChange, this._paginator.page) + .pipe( + switchMap(() => { + this.isLoading = true; + return this._partnerService.getPartners( + this._paginator.pageIndex, + this._paginator.pageSize, + this._sort.active, + this._sort.direction + ); + }), + map(() => { + this.isLoading = false; + }) + ) + .subscribe(); + } + } + + /** + * On destroy + */ + ngOnDestroy(): void { + // Unsubscribe from all subscriptions + this._unsubscribeAll.next(null); + this._unsubscribeAll.complete(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + viewUserDetail(id: string): void { + let url: string = 'member/user/' + id; + this.router.navigateByUrl(url); + } + // ----------------------------------------------------------------------------------------------------- + // @ Private methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Create product + */ + __createProduct(): void {} + + /** + * Toggle product details + * + * @param productId + */ + __toggleDetails(productId: string): void {} + + /** + * Track by function for ngFor loops + * + * @param index + * @param item + */ + __trackByFn(index: number, item: any): any { + return item.id || index; + } +} diff --git a/src/app/modules/admin/member/partner/models/partner-pagination.ts b/src/app/modules/admin/member/partner/models/partner-pagination.ts new file mode 100644 index 0000000..197cc5d --- /dev/null +++ b/src/app/modules/admin/member/partner/models/partner-pagination.ts @@ -0,0 +1,8 @@ +export interface PartnerPagination { + length: number; + size: number; + page: number; + lastPage: number; + startIndex: number; + endIndex: number; +} diff --git a/src/app/modules/admin/member/partner/models/partner.ts b/src/app/modules/admin/member/partner/models/partner.ts new file mode 100644 index 0000000..97041c0 --- /dev/null +++ b/src/app/modules/admin/member/partner/models/partner.ts @@ -0,0 +1,31 @@ +import { NumberValueAccessor } from '@angular/forms'; + +export interface Partner { + id?: string; + totalMemberCount?: number; + totalHoldingMoney?: number; + totalComp?: number; + nickname?: string; + rank?: string; + branchCount?: number; + divisionCount?: number; + officeCount?: number; + storeCount?: number; + memberCount?: number; + level?: string; + calculateType?: string; + holdingMoney?: number; + accountHolder?: string; + phoneNumber?: string; + comp?: number; + coupon?: number; + ownCharge?: number; + bottomCharge?: number; + ownExchange?: number; + bottomExchange?: number; + ownRevenue?: number; + bottomRevenue?: number; + accession?: string; + state?: string; + note?: string; +} diff --git a/src/app/modules/admin/member/partner/partner.module.ts b/src/app/modules/admin/member/partner/partner.module.ts new file mode 100644 index 0000000..563378d --- /dev/null +++ b/src/app/modules/admin/member/partner/partner.module.ts @@ -0,0 +1,48 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { MatButtonModule } from '@angular/material/button'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatPaginatorModule } from '@angular/material/paginator'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { MatRippleModule } from '@angular/material/core'; +import { MatSortModule } from '@angular/material/sort'; +import { MatSelectModule } from '@angular/material/select'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { MatGridListModule } from '@angular/material/grid-list'; +import { MatSlideToggleModule } from '@angular/material/slide-toggle'; +import { MatRadioModule } from '@angular/material/radio'; + +import { TranslocoModule } from '@ngneat/transloco'; + +import { SharedModule } from 'app/shared/shared.module'; + +import { COMPONENTS } from './components'; + +import { partnerRoutes } from './partner.routing'; + +@NgModule({ + declarations: [COMPONENTS], + imports: [ + TranslocoModule, + SharedModule, + RouterModule.forChild(partnerRoutes), + + MatButtonModule, + MatFormFieldModule, + MatIconModule, + MatInputModule, + MatPaginatorModule, + MatProgressBarModule, + MatRippleModule, + MatSortModule, + MatSelectModule, + MatTooltipModule, + MatGridListModule, + MatSlideToggleModule, + MatRadioModule, + ], +}) +export class PartnerModule {} diff --git a/src/app/modules/admin/member/partner/partner.routing.ts b/src/app/modules/admin/member/partner/partner.routing.ts new file mode 100644 index 0000000..0cf0c5c --- /dev/null +++ b/src/app/modules/admin/member/partner/partner.routing.ts @@ -0,0 +1,24 @@ +import { Route } from '@angular/router'; + +import { ListComponent } from './components/list.component'; +import { ViewComponent } from '../user/components/view.component'; + +import { PartnersResolver } from './resolvers/partner.resolver'; +import { UserResolver } from '../user/resolvers/user.resolver'; + +export const partnerRoutes: Route[] = [ + { + path: '', + component: ListComponent, + resolve: { + Partners: PartnersResolver, + }, + }, + { + path: ':id', + component: ViewComponent, + resolve: { + users: UserResolver, + }, + }, +]; diff --git a/src/app/modules/admin/member/partner/resolvers/partner.resolver.ts b/src/app/modules/admin/member/partner/resolvers/partner.resolver.ts new file mode 100644 index 0000000..26b00c2 --- /dev/null +++ b/src/app/modules/admin/member/partner/resolvers/partner.resolver.ts @@ -0,0 +1,89 @@ +import { Injectable } from '@angular/core'; +import { + ActivatedRouteSnapshot, + Resolve, + Router, + RouterStateSnapshot, +} from '@angular/router'; +import { catchError, Observable, throwError } from 'rxjs'; + +import { Partner } from '../models/partner'; +import { PartnerPagination } from '../models/partner-pagination'; +import { PartnerService } from '../services/partner.service'; + +@Injectable({ + providedIn: 'root', +}) +export class PartnerResolver implements Resolve { + /** + * Constructor + */ + constructor( + private _partnerServiceService: PartnerService, + private _router: Router + ) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Resolver + * + * @param route + * @param state + */ + resolve( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable { + return this._partnerServiceService + .getPartnerById(route.paramMap.get('id')) + .pipe( + // Error here means the requested product is not available + catchError((error) => { + // Log the error + console.error(error); + + // Get the parent url + const parentUrl = state.url.split('/').slice(0, -1).join('/'); + + // Navigate to there + this._router.navigateByUrl(parentUrl); + + // Throw an error + return throwError(error); + }) + ); + } +} + +@Injectable({ + providedIn: 'root', +}) +export class PartnersResolver implements Resolve { + /** + * Constructor + */ + constructor(private _partnerService: PartnerService) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Resolver + * + * @param route + * @param state + */ + resolve( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable<{ + pagination: PartnerPagination; + partners: Partner[]; + }> { + return this._partnerService.getPartners(); + } +} diff --git a/src/app/modules/admin/member/partner/services/partner.service.ts b/src/app/modules/admin/member/partner/services/partner.service.ts new file mode 100644 index 0000000..f721cd7 --- /dev/null +++ b/src/app/modules/admin/member/partner/services/partner.service.ts @@ -0,0 +1,153 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { + BehaviorSubject, + filter, + map, + Observable, + of, + switchMap, + take, + tap, + throwError, +} from 'rxjs'; + +import { Partner } from '../models/partner'; +import { PartnerPagination } from '../models/partner-pagination'; + +@Injectable({ + providedIn: 'root', +}) +export class PartnerService { + // Private + private __pagination = new BehaviorSubject( + undefined + ); + private __partner = new BehaviorSubject(undefined); + private __partners = new BehaviorSubject(undefined); + + /** + * Constructor + */ + constructor(private _httpClient: HttpClient) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Accessors + // ----------------------------------------------------------------------------------------------------- + + /** + * Getter for pagination + */ + get pagination$(): Observable { + return this.__pagination.asObservable(); + } + + /** + * Getter for partner + */ + get partner$(): Observable { + return this.__partner.asObservable(); + } + + /** + * Getter for partners + */ + get partners$(): Observable { + return this.__partners.asObservable(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Get partners + * + * + * @param page + * @param size + * @param sort + * @param order + * @param search + */ + getPartners( + page: number = 0, + size: number = 10, + sort: string = 'name', + order: 'asc' | 'desc' | '' = 'asc', + search: string = '' + ): Observable<{ + pagination: PartnerPagination; + partners: Partner[]; + }> { + return this._httpClient + .get<{ pagination: PartnerPagination; partners: Partner[] }>( + 'api/apps/member/partner/partners', + { + params: { + page: '' + page, + size: '' + size, + sort, + order, + search, + }, + } + ) + .pipe( + tap((response) => { + this.__pagination.next(response.pagination); + this.__partners.next(response.partners); + }) + ); + } + + /** + * Get product by id + */ + getPartnerById(id: string | null): Observable { + return this.__partners.pipe( + take(1), + map((partners) => { + // Find the product + const partner = partners?.find((item) => item.id === id) || undefined; + + // Update the product + this.__partner.next(partner); + + // Return the product + return partner; + }), + switchMap((product) => { + if (!product) { + return throwError('Could not found product with id of ' + id + '!'); + } + + return of(product); + }) + ); + } + + /** + * Create product + */ + createPartner(): Observable { + return this.partners$.pipe( + take(1), + switchMap((partners) => + this._httpClient + .post('api/apps/member/partner/product', {}) + .pipe( + map((newPartner) => { + // Update the partners with the new product + if (!!partners) { + this.__partners.next([newPartner, ...partners]); + } + + // Return the new product + return newPartner; + }) + ) + ) + ); + } +} diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 7adc722..340b53c 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -6,7 +6,8 @@ "Casinomoney": "Casinomoney", "Unconnected": "Unconnected", "Project": "Project", - "Partner": "Partner", + "All Partner": "All Partner", + "Mainoffice": "Mainoffice", "Analytics": "Analytics", "Deposit": "Deposit", "Withdraw": "Withdraw", diff --git a/src/assets/i18n/ko.json b/src/assets/i18n/ko.json index 42edda1..4177cea 100644 --- a/src/assets/i18n/ko.json +++ b/src/assets/i18n/ko.json @@ -6,7 +6,7 @@ "Casinomoney": "CASINO 머니파악", "Unconnected": "장기미접속회원", "Project": "프로젝트", - "Partner": "파트너", + "All Partner": "전체파트너", "Analytics": "Analytics", "Deposit": "입금관리", "Withdraw": "출금관리", From 5fbcd6aa282617e5b838c5b1a9910dca837b7b39 Mon Sep 17 00:00:00 2001 From: JUNG YI DAM Date: Tue, 12 Jul 2022 13:32:33 +0000 Subject: [PATCH 2/8] =?UTF-8?q?=ED=8C=8C=ED=8A=B8=EB=84=88=20=EB=B3=B8?= =?UTF-8?q?=EC=82=AC=20page=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.routing.ts | 7 + .../apps/member/partner-branch/api.ts | 223 +++++++++++ .../apps/member/partner-branch/data.ts | 33 ++ src/app/mock-api/common/navigation/data.ts | 7 + src/app/mock-api/index.ts | 2 + .../member/partner-branch/components/index.ts | 3 + .../components/list.component.html | 363 ++++++++++++++++++ .../components/list.component.ts | 198 ++++++++++ .../models/partner-branch-pagination.ts | 8 + .../partner-branch/models/partner-branch.ts | 29 ++ .../partner-branch/partner-branch.module.ts | 50 +++ .../partner-branch/partner-branch.routing.ts | 24 ++ .../resolvers/partner-branch.resolver.ts | 89 +++++ .../services/Partner-branch.service.ts | 161 ++++++++ src/assets/i18n/en.json | 1 + src/assets/i18n/ko.json | 1 + 16 files changed, 1199 insertions(+) create mode 100644 src/app/mock-api/apps/member/partner-branch/api.ts create mode 100644 src/app/mock-api/apps/member/partner-branch/data.ts create mode 100644 src/app/modules/admin/member/partner-branch/components/index.ts create mode 100644 src/app/modules/admin/member/partner-branch/components/list.component.html create mode 100644 src/app/modules/admin/member/partner-branch/components/list.component.ts create mode 100644 src/app/modules/admin/member/partner-branch/models/partner-branch-pagination.ts create mode 100644 src/app/modules/admin/member/partner-branch/models/partner-branch.ts create mode 100644 src/app/modules/admin/member/partner-branch/partner-branch.module.ts create mode 100644 src/app/modules/admin/member/partner-branch/partner-branch.routing.ts create mode 100644 src/app/modules/admin/member/partner-branch/resolvers/partner-branch.resolver.ts create mode 100644 src/app/modules/admin/member/partner-branch/services/Partner-branch.service.ts diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts index ef10a55..3b6ac0a 100644 --- a/src/app/app.routing.ts +++ b/src/app/app.routing.ts @@ -178,6 +178,13 @@ export const appRoutes: Route[] = [ (m: any) => m.PartnerModule ), }, + { + path: 'partner-branch', + loadChildren: () => + import( + 'app/modules/admin/member/partner-branch/partner-branch.module' + ).then((m: any) => m.PartnerBranchModule), + }, ], }, { diff --git a/src/app/mock-api/apps/member/partner-branch/api.ts b/src/app/mock-api/apps/member/partner-branch/api.ts new file mode 100644 index 0000000..0eba1aa --- /dev/null +++ b/src/app/mock-api/apps/member/partner-branch/api.ts @@ -0,0 +1,223 @@ +import { Injectable } from '@angular/core'; +import { assign, cloneDeep } from 'lodash-es'; +import { FuseMockApiService, FuseMockApiUtils } from '@fuse/lib/mock-api'; +import { partnerBranchs as partnerBranchsData } from './data'; + +@Injectable({ + providedIn: 'root', +}) +export class MemberPartnerBranchMockApi { + private _partnerBranchs: any[] = partnerBranchsData; + + /** + * Constructor + */ + constructor(private _fuseMockApiService: FuseMockApiService) { + // Register Mock API handlers + this.registerHandlers(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Register Mock API handlers + */ + registerHandlers(): void { + // ----------------------------------------------------------------------------------------------------- + // @ PartnerBranchs - GET + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onGet('api/apps/member/partner-branch/partner-branchs', 300) + .reply(({ request }) => { + // Get available queries + const search = request.params.get('search'); + const sort = request.params.get('sort') || 'name'; + const order = request.params.get('order') || 'asc'; + const page = parseInt(request.params.get('page') ?? '1', 10); + const size = parseInt(request.params.get('size') ?? '10', 10); + + // Clone the partnerBranchs + let partnerBranchs: any[] | null = cloneDeep(this._partnerBranchs); + + // Sort the partnerBranchs + if (sort === 'sku' || sort === 'name' || sort === 'active') { + partnerBranchs.sort((a, b) => { + const fieldA = a[sort].toString().toUpperCase(); + const fieldB = b[sort].toString().toUpperCase(); + return order === 'asc' + ? fieldA.localeCompare(fieldB) + : fieldB.localeCompare(fieldA); + }); + } else { + partnerBranchs.sort((a, b) => + order === 'asc' ? a[sort] - b[sort] : b[sort] - a[sort] + ); + } + + // If search exists... + if (search) { + // Filter the partnerBranchs + partnerBranchs = partnerBranchs.filter( + (contact: any) => + contact.name && + contact.name.toLowerCase().includes(search.toLowerCase()) + ); + } + + // Paginate - Start + const partnerBranchsLength = partnerBranchs.length; + + // Calculate pagination details + const begin = page * size; + const end = Math.min(size * (page + 1), partnerBranchsLength); + const lastPage = Math.max(Math.ceil(partnerBranchsLength / size), 1); + + // Prepare the pagination object + let pagination = {}; + + // If the requested page number is bigger than + // the last possible page number, return null for + // partnerBranchs but also send the last possible page so + // the app can navigate to there + if (page > lastPage) { + partnerBranchs = null; + pagination = { + lastPage, + }; + } else { + // Paginate the results by size + partnerBranchs = partnerBranchs.slice(begin, end); + + // Prepare the pagination mock-api + pagination = { + length: partnerBranchsLength, + size: size, + page: page, + lastPage: lastPage, + startIndex: begin, + endIndex: end - 1, + }; + } + + // Return the response + return [ + 200, + { + partnerBranchs, + pagination, + }, + ]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerBranch - GET + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onGet('api/apps/member/partne-branch/partner-branch') + .reply(({ request }) => { + // Get the id from the params + const id = request.params.get('id'); + + // Clone the partnerBranchs + const partnerBranchs = cloneDeep(this._partnerBranchs); + + // Find the partnerBranch + const partnerBranch = partnerBranchs.find( + (item: any) => item.id === id + ); + + // Return the response + return [200, partnerBranch]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerBranch - POST + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onPost('api/apps/member/partner-branch/partner-branch') + .reply(() => { + // Generate a new partnerBranch + const newPartnerBranch = { + id: FuseMockApiUtils.guid(), + category: '', + name: 'A New User', + description: '', + tags: [], + sku: '', + barcode: '', + brand: '', + vendor: '', + stock: '', + reserved: '', + cost: '', + basePrice: '', + taxPercent: '', + price: '', + weight: '', + thumbnail: '', + images: [], + active: false, + }; + + // Unshift the new partnerBranch + this._partnerBranchs.unshift(newPartnerBranch); + + // Return the response + return [200, newPartnerBranch]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerBranch - PATCH + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onPatch('api/apps/member/partner-branch/partner-branch') + .reply(({ request }) => { + // Get the id and partnerBranch + const id = request.body.id; + const partnerBranch = cloneDeep(request.body.partnerBranch); + + // Prepare the updated partnerBranch + let updatedPartnerBranch = null; + + // Find the partnerBranch and update it + this._partnerBranchs.forEach((item, index, partnerBranchs) => { + if (item.id === id) { + // Update the partnerBranch + partnerBranchs[index] = assign( + {}, + partnerBranchs[index], + partnerBranch + ); + + // Store the updated partnerBranch + updatedPartnerBranch = partnerBranchs[index]; + } + }); + + // Return the response + return [200, updatedPartnerBranch]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerBranch - DELETE + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onDelete('api/apps/member/partner-branch/partner-branch') + .reply(({ request }) => { + // Get the id + const id = request.params.get('id'); + + // Find the partnerBranch and delete it + this._partnerBranchs.forEach((item, index) => { + if (item.id === id) { + this._partnerBranchs.splice(index, 1); + } + }); + + // Return the response + return [200, true]; + }); + } +} diff --git a/src/app/mock-api/apps/member/partner-branch/data.ts b/src/app/mock-api/apps/member/partner-branch/data.ts new file mode 100644 index 0000000..a75a4ba --- /dev/null +++ b/src/app/mock-api/apps/member/partner-branch/data.ts @@ -0,0 +1,33 @@ +/* eslint-disable */ + +export const partnerBranchs = [ + { + id: 'on00', + totalPartnerCount: '5', + totalHoldingMoney: 303675, + totalComp: 108933, + total: 412608, + branchCount: 1, + divisionCount: 1, + officeCount: 1, + storeCount: 1, + memberCount: 1, + nickname: 'on00', + accountHolder: '11', + phoneNumber: '010-1111-1111', + calculateType: '롤링', + ownCash: 50000, + ownComp: 1711, + ownCoupon: 50000, + gameMoney: 0, + todayComp: 0, + totalDeposit: 0, + totalWithdraw: 0, + balance: 0, + registDate: '2022-06-12 15:38', + finalSigninDate: '', + ip: '', + state: '정상', + note: '대본등록', + }, +]; diff --git a/src/app/mock-api/common/navigation/data.ts b/src/app/mock-api/common/navigation/data.ts index b7399fd..d8b2ae2 100644 --- a/src/app/mock-api/common/navigation/data.ts +++ b/src/app/mock-api/common/navigation/data.ts @@ -74,6 +74,13 @@ export const defaultNavigation: FuseNavigationItem[] = [ icon: 'heroicons_outline:academic-cap', link: '/member/partner', }, + { + id: 'member.partner-branch', + title: 'Partner Branch', + type: 'basic', + icon: 'heroicons_outline:academic-cap', + link: '/member/partner-branch', + }, ], }, { diff --git a/src/app/mock-api/index.ts b/src/app/mock-api/index.ts index 365f7b9..6f1c591 100644 --- a/src/app/mock-api/index.ts +++ b/src/app/mock-api/index.ts @@ -16,6 +16,7 @@ import { MemberCasinomoneyMockApi } from './apps/member/casinomoney/api'; import { MemberUnconnectedMockApi } from './apps/member/unconnected/api'; import { MemberCurrentUserMockApi } from './apps/member/current-user/api'; import { MemberPartnerMockApi } from './apps/member/partner/partner-api'; +import { MemberPartnerBranchMockApi } from './apps/member/partner-branch/api'; import { MessagesMockApi } from 'app/mock-api/common/messages/api'; import { NavigationMockApi } from 'app/mock-api/common/navigation/api'; import { NotesMockApi } from 'app/mock-api/apps/notes/api'; @@ -52,6 +53,7 @@ export const mockApiServices = [ MemberUnconnectedMockApi, MemberCurrentUserMockApi, MemberPartnerMockApi, + MemberPartnerBranchMockApi, MessagesMockApi, NavigationMockApi, NotesMockApi, diff --git a/src/app/modules/admin/member/partner-branch/components/index.ts b/src/app/modules/admin/member/partner-branch/components/index.ts new file mode 100644 index 0000000..04759eb --- /dev/null +++ b/src/app/modules/admin/member/partner-branch/components/index.ts @@ -0,0 +1,3 @@ +import { ListComponent } from './list.component'; + +export const COMPONENTS = [ListComponent]; diff --git a/src/app/modules/admin/member/partner-branch/components/list.component.html b/src/app/modules/admin/member/partner-branch/components/list.component.html new file mode 100644 index 0000000..92e11d2 --- /dev/null +++ b/src/app/modules/admin/member/partner-branch/components/list.component.html @@ -0,0 +1,363 @@ +
+ +
+ +
+ +
+ +
부본
+ +
+ + + + + + + 40 + 60 + 80 + 100 + + + + + LV.1 + LV.2 + LV.3 + LV.4 + + + + + 정상 + 대기 + 탈퇴 + 휴면 + 블랙 + 정지 + + + + + 카지노제한 + 슬롯제한 + + + + + 계좌입금 + + + + + 카지노콤프 + 슬롯콤프 + 배팅콤프 + 첫충콤프 + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + +
+
+ + +
+ There are no partnerbranchs! +
+
+
+
+
diff --git a/src/app/modules/admin/member/partner-branch/components/list.component.ts b/src/app/modules/admin/member/partner-branch/components/list.component.ts new file mode 100644 index 0000000..8bd1f17 --- /dev/null +++ b/src/app/modules/admin/member/partner-branch/components/list.component.ts @@ -0,0 +1,198 @@ +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + OnDestroy, + OnInit, + ViewChild, + ViewEncapsulation, +} from '@angular/core'; +import { + FormBuilder, + FormControl, + FormGroup, + Validators, +} from '@angular/forms'; +import { MatCheckboxChange } from '@angular/material/checkbox'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { + debounceTime, + map, + merge, + Observable, + Subject, + switchMap, + takeUntil, +} from 'rxjs'; +import { fuseAnimations } from '@fuse/animations'; +import { FuseConfirmationService } from '@fuse/services/confirmation'; + +import { User } from '../../user/models/user'; +import { PartnerBranch } from '../models/partner-branch'; +import { PartnerBranchPagination } from '../models/partner-branch-pagination'; +import { PartnerBranchService } from '../services/Partner-branch.service'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'partner-branch-list', + templateUrl: './list.component.html', + styles: [ + /* language=SCSS */ + ` + .inventory-grid { + grid-template-columns: 60px auto 40px; + + @screen sm { + grid-template-columns: 60px 60px 60px 60px 60px 60px auto 60px; + } + + @screen md { + grid-template-columns: 60px 60px 60px 60px 60px 60px auto 60px 60px; + } + + @screen lg { + grid-template-columns: 60px 70px 70px 70px 70px 100px 60px 60px auto 60px 60px 60px 60px; + } + } + `, + ], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush, + animations: fuseAnimations, +}) +export class ListComponent implements OnInit, AfterViewInit, OnDestroy { + @ViewChild(MatPaginator) private _paginator!: MatPaginator; + @ViewChild(MatSort) private _sort!: MatSort; + + partnerBranchs$!: Observable; + users$!: Observable; + + isLoading = false; + searchInputControl = new FormControl(); + selectedPartnerBranch?: PartnerBranch; + pagination?: PartnerBranchPagination; + + private _unsubscribeAll: Subject = new Subject(); + + /** + * Constructor + */ + constructor( + private _changeDetectorRef: ChangeDetectorRef, + private _fuseConfirmationService: FuseConfirmationService, + private _formBuilder: FormBuilder, + private _partnerBranchService: PartnerBranchService, + private router: Router + ) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Lifecycle hooks + // ----------------------------------------------------------------------------------------------------- + + /** + * On init + */ + ngOnInit(): void { + // Get the pagination + this._partnerBranchService.pagination$ + .pipe(takeUntil(this._unsubscribeAll)) + .subscribe((pagination: PartnerBranchPagination | undefined) => { + // Update the pagination + this.pagination = pagination; + + // Mark for check + this._changeDetectorRef.markForCheck(); + }); + + // Get the products + this.partnerBranchs$ = this._partnerBranchService.partnerBranchs$; + } + + /** + * After view init + */ + ngAfterViewInit(): void { + if (this._sort && this._paginator) { + // Set the initial sort + this._sort.sort({ + id: 'name', + start: 'asc', + disableClear: true, + }); + + // Mark for check + this._changeDetectorRef.markForCheck(); + + // If the partnerBranch changes the sort order... + this._sort.sortChange + .pipe(takeUntil(this._unsubscribeAll)) + .subscribe(() => { + // Reset back to the first page + this._paginator.pageIndex = 0; + }); + + // Get products if sort or page changes + merge(this._sort.sortChange, this._paginator.page) + .pipe( + switchMap(() => { + this.isLoading = true; + return this._partnerBranchService.getPartnerBranchs( + this._paginator.pageIndex, + this._paginator.pageSize, + this._sort.active, + this._sort.direction + ); + }), + map(() => { + this.isLoading = false; + }) + ) + .subscribe(); + } + } + + /** + * On destroy + */ + ngOnDestroy(): void { + // Unsubscribe from all subscriptions + this._unsubscribeAll.next(null); + this._unsubscribeAll.complete(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + viewUserDetail(id: string): void { + let url: string = 'member/user/' + id; + this.router.navigateByUrl(url); + } + // ----------------------------------------------------------------------------------------------------- + // @ Private methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Create product + */ + __createProduct(): void {} + + /** + * Toggle product details + * + * @param productId + */ + __toggleDetails(productId: string): void {} + + /** + * Track by function for ngFor loops + * + * @param index + * @param item + */ + __trackByFn(index: number, item: any): any { + return item.id || index; + } +} diff --git a/src/app/modules/admin/member/partner-branch/models/partner-branch-pagination.ts b/src/app/modules/admin/member/partner-branch/models/partner-branch-pagination.ts new file mode 100644 index 0000000..8f33186 --- /dev/null +++ b/src/app/modules/admin/member/partner-branch/models/partner-branch-pagination.ts @@ -0,0 +1,8 @@ +export interface PartnerBranchPagination { + length: number; + size: number; + page: number; + lastPage: number; + startIndex: number; + endIndex: number; +} diff --git a/src/app/modules/admin/member/partner-branch/models/partner-branch.ts b/src/app/modules/admin/member/partner-branch/models/partner-branch.ts new file mode 100644 index 0000000..c681404 --- /dev/null +++ b/src/app/modules/admin/member/partner-branch/models/partner-branch.ts @@ -0,0 +1,29 @@ +export interface PartnerBranch { + id?: string; + totalPartnerCount?: number; + totalHoldingMoney?: number; + totalComp?: number; + total?: number; + branchCount?: number; + divisionCount?: number; + officeCount?: number; + storeCount?: number; + memberCount?: number; + nickname?: string; + accountHolder?: string; + phoneNumber?: string; + calculateType?: string; + ownCash?: number; + ownComp?: number; + ownCoupon?: number; + gameMoney?: number; + todayComp?: number; + totalDeposit?: number; + totalWithdraw?: number; + balance?: number; + registDate?: string; + finalSigninDate?: string; + ip?: string; + state?: string; + note?: string; +} diff --git a/src/app/modules/admin/member/partner-branch/partner-branch.module.ts b/src/app/modules/admin/member/partner-branch/partner-branch.module.ts new file mode 100644 index 0000000..bbb22c0 --- /dev/null +++ b/src/app/modules/admin/member/partner-branch/partner-branch.module.ts @@ -0,0 +1,50 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { MatButtonModule } from '@angular/material/button'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatPaginatorModule } from '@angular/material/paginator'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { MatRippleModule } from '@angular/material/core'; +import { MatSortModule } from '@angular/material/sort'; +import { MatSelectModule } from '@angular/material/select'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { MatGridListModule } from '@angular/material/grid-list'; +import { MatSlideToggleModule } from '@angular/material/slide-toggle'; +import { MatRadioModule } from '@angular/material/radio'; +import { MatCheckboxModule } from '@angular/material/checkbox'; + +import { TranslocoModule } from '@ngneat/transloco'; + +import { SharedModule } from 'app/shared/shared.module'; + +import { COMPONENTS } from './components'; + +import { partnerBranchRoutes } from './partner-branch.routing'; + +@NgModule({ + declarations: [COMPONENTS], + imports: [ + TranslocoModule, + SharedModule, + RouterModule.forChild(partnerBranchRoutes), + + MatButtonModule, + MatFormFieldModule, + MatIconModule, + MatInputModule, + MatPaginatorModule, + MatProgressBarModule, + MatRippleModule, + MatSortModule, + MatSelectModule, + MatTooltipModule, + MatGridListModule, + MatSlideToggleModule, + MatRadioModule, + MatCheckboxModule, + ], +}) +export class PartnerBranchModule {} diff --git a/src/app/modules/admin/member/partner-branch/partner-branch.routing.ts b/src/app/modules/admin/member/partner-branch/partner-branch.routing.ts new file mode 100644 index 0000000..a4b5292 --- /dev/null +++ b/src/app/modules/admin/member/partner-branch/partner-branch.routing.ts @@ -0,0 +1,24 @@ +import { Route } from '@angular/router'; + +import { ListComponent } from './components/list.component'; +import { ViewComponent } from '../user/components/view.component'; + +import { PartnerBranchsResolver } from './resolvers/partner-branch.resolver'; +import { UserResolver } from '../user/resolvers/user.resolver'; + +export const partnerBranchRoutes: Route[] = [ + { + path: '', + component: ListComponent, + resolve: { + partnerBranchs: PartnerBranchsResolver, + }, + }, + { + path: ':id', + component: ViewComponent, + resolve: { + users: UserResolver, + }, + }, +]; diff --git a/src/app/modules/admin/member/partner-branch/resolvers/partner-branch.resolver.ts b/src/app/modules/admin/member/partner-branch/resolvers/partner-branch.resolver.ts new file mode 100644 index 0000000..fd237e8 --- /dev/null +++ b/src/app/modules/admin/member/partner-branch/resolvers/partner-branch.resolver.ts @@ -0,0 +1,89 @@ +import { Injectable } from '@angular/core'; +import { + ActivatedRouteSnapshot, + Resolve, + Router, + RouterStateSnapshot, +} from '@angular/router'; +import { catchError, Observable, throwError } from 'rxjs'; + +import { PartnerBranch } from '../models/partner-branch'; +import { PartnerBranchPagination } from '../models/partner-branch-pagination'; +import { PartnerBranchService } from '../services/Partner-branch.service'; + +@Injectable({ + providedIn: 'root', +}) +export class PartnerBranchResolver implements Resolve { + /** + * Constructor + */ + constructor( + private _partnerBranchService: PartnerBranchService, + private _router: Router + ) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Resolver + * + * @param route + * @param state + */ + resolve( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable { + return this._partnerBranchService + .getPartnerBranchById(route.paramMap.get('id')) + .pipe( + // Error here means the requested product is not available + catchError((error) => { + // Log the error + console.error(error); + + // Get the parent url + const parentUrl = state.url.split('/').slice(0, -1).join('/'); + + // Navigate to there + this._router.navigateByUrl(parentUrl); + + // Throw an error + return throwError(error); + }) + ); + } +} + +@Injectable({ + providedIn: 'root', +}) +export class PartnerBranchsResolver implements Resolve { + /** + * Constructor + */ + constructor(private _partnerBranchService: PartnerBranchService) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Resolver + * + * @param route + * @param state + */ + resolve( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable<{ + pagination: PartnerBranchPagination; + partnerBranchs: PartnerBranch[]; + }> { + return this._partnerBranchService.getPartnerBranchs(); + } +} diff --git a/src/app/modules/admin/member/partner-branch/services/Partner-branch.service.ts b/src/app/modules/admin/member/partner-branch/services/Partner-branch.service.ts new file mode 100644 index 0000000..aa0d372 --- /dev/null +++ b/src/app/modules/admin/member/partner-branch/services/Partner-branch.service.ts @@ -0,0 +1,161 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { + BehaviorSubject, + filter, + map, + Observable, + of, + switchMap, + take, + tap, + throwError, +} from 'rxjs'; + +import { PartnerBranch } from '../models/partner-branch'; +import { PartnerBranchPagination } from '../models/partner-branch-pagination'; + +@Injectable({ + providedIn: 'root', +}) +export class PartnerBranchService { + // Private + private __pagination = new BehaviorSubject< + PartnerBranchPagination | undefined + >(undefined); + private __partnerBranch = new BehaviorSubject( + undefined + ); + private __partnerBranchs = new BehaviorSubject( + undefined + ); + + /** + * Constructor + */ + constructor(private _httpClient: HttpClient) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Accessors + // ----------------------------------------------------------------------------------------------------- + + /** + * Getter for pagination + */ + get pagination$(): Observable { + return this.__pagination.asObservable(); + } + + /** + * Getter for partnerBranch + */ + get partnerBranch$(): Observable { + return this.__partnerBranch.asObservable(); + } + + /** + * Getter for partnerBranchs + */ + get partnerBranchs$(): Observable { + return this.__partnerBranchs.asObservable(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Get partnerBranchs + * + * + * @param page + * @param size + * @param sort + * @param order + * @param search + */ + getPartnerBranchs( + page: number = 0, + size: number = 10, + sort: string = 'name', + order: 'asc' | 'desc' | '' = 'asc', + search: string = '' + ): Observable<{ + pagination: PartnerBranchPagination; + partnerBranchs: PartnerBranch[]; + }> { + return this._httpClient + .get<{ + pagination: PartnerBranchPagination; + partnerBranchs: PartnerBranch[]; + }>('api/apps/member/partner-branch/partner-branchs', { + params: { + page: '' + page, + size: '' + size, + sort, + order, + search, + }, + }) + .pipe( + tap((response) => { + this.__pagination.next(response.pagination); + this.__partnerBranchs.next(response.partnerBranchs); + }) + ); + } + + /** + * Get product by id + */ + getPartnerBranchById(id: string | null): Observable { + return this.__partnerBranchs.pipe( + take(1), + map((partnerBranchs) => { + // Find the product + const partnerBranch = + partnerBranchs?.find((item) => item.id === id) || undefined; + + // Update the product + this.__partnerBranch.next(partnerBranch); + + // Return the product + return partnerBranch; + }), + switchMap((product) => { + if (!product) { + return throwError('Could not found product with id of ' + id + '!'); + } + + return of(product); + }) + ); + } + + /** + * Create product + */ + createPartnerBranch(): Observable { + return this.partnerBranchs$.pipe( + take(1), + switchMap((partnerBranchs) => + this._httpClient + .post('api/apps/member/partner-branch/product', {}) + .pipe( + map((newPartnerBranch) => { + // Update the partnerBranchs with the new product + if (!!partnerBranchs) { + this.__partnerBranchs.next([ + newPartnerBranch, + ...partnerBranchs, + ]); + } + + // Return the new product + return newPartnerBranch; + }) + ) + ) + ); + } +} diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 340b53c..712affa 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -7,6 +7,7 @@ "Unconnected": "Unconnected", "Project": "Project", "All Partner": "All Partner", + "Partner Branch": "Partner Branch", "Mainoffice": "Mainoffice", "Analytics": "Analytics", "Deposit": "Deposit", diff --git a/src/assets/i18n/ko.json b/src/assets/i18n/ko.json index 4177cea..413193c 100644 --- a/src/assets/i18n/ko.json +++ b/src/assets/i18n/ko.json @@ -7,6 +7,7 @@ "Unconnected": "장기미접속회원", "Project": "프로젝트", "All Partner": "전체파트너", + "Partner Branch": "부본", "Analytics": "Analytics", "Deposit": "입금관리", "Withdraw": "출금관리", From 48af3a9a719f0bb52058826c1544bbb4ab36e224 Mon Sep 17 00:00:00 2001 From: JUNG YI DAM Date: Wed, 13 Jul 2022 00:54:15 +0000 Subject: [PATCH 3/8] =?UTF-8?q?=ED=8C=8C=EC=9D=BC=EB=AA=85=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/mock-api/apps/member/partner/{partner-api.ts => api.ts} | 2 +- .../mock-api/apps/member/partner/{partner-data.ts => data.ts} | 0 src/app/mock-api/index.ts | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/app/mock-api/apps/member/partner/{partner-api.ts => api.ts} (99%) rename src/app/mock-api/apps/member/partner/{partner-data.ts => data.ts} (100%) diff --git a/src/app/mock-api/apps/member/partner/partner-api.ts b/src/app/mock-api/apps/member/partner/api.ts similarity index 99% rename from src/app/mock-api/apps/member/partner/partner-api.ts rename to src/app/mock-api/apps/member/partner/api.ts index b94ffa5..aec6a86 100644 --- a/src/app/mock-api/apps/member/partner/partner-api.ts +++ b/src/app/mock-api/apps/member/partner/api.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { assign, cloneDeep } from 'lodash-es'; import { FuseMockApiService, FuseMockApiUtils } from '@fuse/lib/mock-api'; -import { partners as partnersData } from './partner-data'; +import { partners as partnersData } from './data'; @Injectable({ providedIn: 'root', diff --git a/src/app/mock-api/apps/member/partner/partner-data.ts b/src/app/mock-api/apps/member/partner/data.ts similarity index 100% rename from src/app/mock-api/apps/member/partner/partner-data.ts rename to src/app/mock-api/apps/member/partner/data.ts diff --git a/src/app/mock-api/index.ts b/src/app/mock-api/index.ts index 6f1c591..cce36c5 100644 --- a/src/app/mock-api/index.ts +++ b/src/app/mock-api/index.ts @@ -15,7 +15,7 @@ import { MemberUserMockApi } from 'app/mock-api/apps/member/user/api'; import { MemberCasinomoneyMockApi } from './apps/member/casinomoney/api'; import { MemberUnconnectedMockApi } from './apps/member/unconnected/api'; import { MemberCurrentUserMockApi } from './apps/member/current-user/api'; -import { MemberPartnerMockApi } from './apps/member/partner/partner-api'; +import { MemberPartnerMockApi } from './apps/member/partner/api'; import { MemberPartnerBranchMockApi } from './apps/member/partner-branch/api'; import { MessagesMockApi } from 'app/mock-api/common/messages/api'; import { NavigationMockApi } from 'app/mock-api/common/navigation/api'; From 2d8e2b02b455030098bc14bbbff66914c149113d Mon Sep 17 00:00:00 2001 From: JUNG YI DAM Date: Wed, 13 Jul 2022 00:57:16 +0000 Subject: [PATCH 4/8] fix --- .../member/partner-branch/components/list.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/modules/admin/member/partner-branch/components/list.component.html b/src/app/modules/admin/member/partner-branch/components/list.component.html index 92e11d2..ff464c3 100644 --- a/src/app/modules/admin/member/partner-branch/components/list.component.html +++ b/src/app/modules/admin/member/partner-branch/components/list.component.html @@ -10,7 +10,7 @@ -
부본
+
대본
@@ -331,7 +331,7 @@
From d05227816ab7ca454fb092919a833134459970ec Mon Sep 17 00:00:00 2001 From: JUNG YI DAM Date: Wed, 13 Jul 2022 01:29:00 +0000 Subject: [PATCH 5/8] =?UTF-8?q?=ED=8C=8C=ED=8A=B8=EB=84=88=20=EB=B6=80?= =?UTF-8?q?=EB=B3=B8=20page=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.routing.ts | 7 + .../apps/member/partner-division/api.ts | 223 +++++++++++ .../apps/member/partner-division/data.ts | 33 ++ src/app/mock-api/common/navigation/data.ts | 7 + src/app/mock-api/index.ts | 2 + .../partner-division/components/index.ts | 3 + .../components/list.component.html | 365 ++++++++++++++++++ .../components/list.component.ts | 198 ++++++++++ .../models/partner-division-pagination.ts | 8 + .../models/partner-division.ts | 29 ++ .../partner-division.module.ts | 50 +++ .../partner-division.routing.ts | 24 ++ .../resolvers/partner-division.resolver.ts | 89 +++++ .../services/Partner-division.service.ts | 161 ++++++++ src/assets/i18n/en.json | 1 + src/assets/i18n/ko.json | 3 +- 16 files changed, 1202 insertions(+), 1 deletion(-) create mode 100644 src/app/mock-api/apps/member/partner-division/api.ts create mode 100644 src/app/mock-api/apps/member/partner-division/data.ts create mode 100644 src/app/modules/admin/member/partner-division/components/index.ts create mode 100644 src/app/modules/admin/member/partner-division/components/list.component.html create mode 100644 src/app/modules/admin/member/partner-division/components/list.component.ts create mode 100644 src/app/modules/admin/member/partner-division/models/partner-division-pagination.ts create mode 100644 src/app/modules/admin/member/partner-division/models/partner-division.ts create mode 100644 src/app/modules/admin/member/partner-division/partner-division.module.ts create mode 100644 src/app/modules/admin/member/partner-division/partner-division.routing.ts create mode 100644 src/app/modules/admin/member/partner-division/resolvers/partner-division.resolver.ts create mode 100644 src/app/modules/admin/member/partner-division/services/Partner-division.service.ts diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts index 3b6ac0a..7d3aa7e 100644 --- a/src/app/app.routing.ts +++ b/src/app/app.routing.ts @@ -185,6 +185,13 @@ export const appRoutes: Route[] = [ 'app/modules/admin/member/partner-branch/partner-branch.module' ).then((m: any) => m.PartnerBranchModule), }, + { + path: 'partner-division', + loadChildren: () => + import( + 'app/modules/admin/member/partner-division/partner-division.module' + ).then((m: any) => m.PartnerDivisionModule), + }, ], }, { diff --git a/src/app/mock-api/apps/member/partner-division/api.ts b/src/app/mock-api/apps/member/partner-division/api.ts new file mode 100644 index 0000000..4b9ff47 --- /dev/null +++ b/src/app/mock-api/apps/member/partner-division/api.ts @@ -0,0 +1,223 @@ +import { Injectable } from '@angular/core'; +import { assign, cloneDeep } from 'lodash-es'; +import { FuseMockApiService, FuseMockApiUtils } from '@fuse/lib/mock-api'; +import { partnerDivisions as partnerDivisionsData } from './data'; + +@Injectable({ + providedIn: 'root', +}) +export class MemberPartnerDivisionMockApi { + private _partnerDivisions: any[] = partnerDivisionsData; + + /** + * Constructor + */ + constructor(private _fuseMockApiService: FuseMockApiService) { + // Register Mock API handlers + this.registerHandlers(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Register Mock API handlers + */ + registerHandlers(): void { + // ----------------------------------------------------------------------------------------------------- + // @ PartnerDivisions - GET + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onGet('api/apps/member/partner-division/partner-divisions', 300) + .reply(({ request }) => { + // Get available queries + const search = request.params.get('search'); + const sort = request.params.get('sort') || 'name'; + const order = request.params.get('order') || 'asc'; + const page = parseInt(request.params.get('page') ?? '1', 10); + const size = parseInt(request.params.get('size') ?? '10', 10); + + // Clone the partnerDivisions + let partnerDivisions: any[] | null = cloneDeep(this._partnerDivisions); + + // Sort the partnerDivisions + if (sort === 'sku' || sort === 'name' || sort === 'active') { + partnerDivisions.sort((a, b) => { + const fieldA = a[sort].toString().toUpperCase(); + const fieldB = b[sort].toString().toUpperCase(); + return order === 'asc' + ? fieldA.localeCompare(fieldB) + : fieldB.localeCompare(fieldA); + }); + } else { + partnerDivisions.sort((a, b) => + order === 'asc' ? a[sort] - b[sort] : b[sort] - a[sort] + ); + } + + // If search exists... + if (search) { + // Filter the partnerDivisions + partnerDivisions = partnerDivisions.filter( + (contact: any) => + contact.name && + contact.name.toLowerCase().includes(search.toLowerCase()) + ); + } + + // Paginate - Start + const partnerDivisionsLength = partnerDivisions.length; + + // Calculate pagination details + const begin = page * size; + const end = Math.min(size * (page + 1), partnerDivisionsLength); + const lastPage = Math.max(Math.ceil(partnerDivisionsLength / size), 1); + + // Prepare the pagination object + let pagination = {}; + + // If the requested page number is bigger than + // the last possible page number, return null for + // partnerDivisions but also send the last possible page so + // the app can navigate to there + if (page > lastPage) { + partnerDivisions = null; + pagination = { + lastPage, + }; + } else { + // Paginate the results by size + partnerDivisions = partnerDivisions.slice(begin, end); + + // Prepare the pagination mock-api + pagination = { + length: partnerDivisionsLength, + size: size, + page: page, + lastPage: lastPage, + startIndex: begin, + endIndex: end - 1, + }; + } + + // Return the response + return [ + 200, + { + partnerDivisions, + pagination, + }, + ]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerDivision - GET + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onGet('api/apps/member/partne-division/partner-division') + .reply(({ request }) => { + // Get the id from the params + const id = request.params.get('id'); + + // Clone the partnerDivisions + const partnerDivisions = cloneDeep(this._partnerDivisions); + + // Find the partnerDivision + const partnerDivision = partnerDivisions.find( + (item: any) => item.id === id + ); + + // Return the response + return [200, partnerDivision]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerDivision - POST + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onPost('api/apps/member/partner-division/partner-division') + .reply(() => { + // Generate a new partnerDivision + const newPartnerDivision = { + id: FuseMockApiUtils.guid(), + category: '', + name: 'A New User', + description: '', + tags: [], + sku: '', + barcode: '', + brand: '', + vendor: '', + stock: '', + reserved: '', + cost: '', + basePrice: '', + taxPercent: '', + price: '', + weight: '', + thumbnail: '', + images: [], + active: false, + }; + + // Unshift the new partnerDivision + this._partnerDivisions.unshift(newPartnerDivision); + + // Return the response + return [200, newPartnerDivision]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerDivision - PATCH + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onPatch('api/apps/member/partner-division/partner-division') + .reply(({ request }) => { + // Get the id and partnerDivision + const id = request.body.id; + const partnerDivision = cloneDeep(request.body.partnerDivision); + + // Prepare the updated partnerDivision + let updatedPartnerDivision = null; + + // Find the partnerDivision and update it + this._partnerDivisions.forEach((item, index, partnerDivisions) => { + if (item.id === id) { + // Update the partnerDivision + partnerDivisions[index] = assign( + {}, + partnerDivisions[index], + partnerDivision + ); + + // Store the updated partnerDivision + updatedPartnerDivision = partnerDivisions[index]; + } + }); + + // Return the response + return [200, updatedPartnerDivision]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerDivision - DELETE + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onDelete('api/apps/member/partner-division/partner-division') + .reply(({ request }) => { + // Get the id + const id = request.params.get('id'); + + // Find the partnerDivision and delete it + this._partnerDivisions.forEach((item, index) => { + if (item.id === id) { + this._partnerDivisions.splice(index, 1); + } + }); + + // Return the response + return [200, true]; + }); + } +} diff --git a/src/app/mock-api/apps/member/partner-division/data.ts b/src/app/mock-api/apps/member/partner-division/data.ts new file mode 100644 index 0000000..e8373d4 --- /dev/null +++ b/src/app/mock-api/apps/member/partner-division/data.ts @@ -0,0 +1,33 @@ +/* eslint-disable */ + +export const partnerDivisions = [ + { + id: 'on00', + totalPartnerCount: '5', + totalHoldingMoney: 303675, + totalComp: 108933, + total: 412608, + branchCount: 1, + divisionCount: 1, + officeCount: 1, + storeCount: 1, + memberCount: 1, + nickname: 'on00', + accountHolder: '11', + phoneNumber: '010-1111-1111', + calculateType: '롤링', + ownCash: 50000, + ownComp: 1711, + ownCoupon: 50000, + gameMoney: 0, + todayComp: 0, + totalDeposit: 0, + totalWithdraw: 0, + balance: 0, + registDate: '2022-06-12 15:38', + finalSigninDate: '', + ip: '', + state: '정상', + note: '대본등록', + }, +]; diff --git a/src/app/mock-api/common/navigation/data.ts b/src/app/mock-api/common/navigation/data.ts index d8b2ae2..321e086 100644 --- a/src/app/mock-api/common/navigation/data.ts +++ b/src/app/mock-api/common/navigation/data.ts @@ -81,6 +81,13 @@ export const defaultNavigation: FuseNavigationItem[] = [ icon: 'heroicons_outline:academic-cap', link: '/member/partner-branch', }, + { + id: 'member.partner-division', + title: 'Partner Division', + type: 'basic', + icon: 'heroicons_outline:academic-cap', + link: '/member/partner-division', + }, ], }, { diff --git a/src/app/mock-api/index.ts b/src/app/mock-api/index.ts index cce36c5..45a883c 100644 --- a/src/app/mock-api/index.ts +++ b/src/app/mock-api/index.ts @@ -17,6 +17,7 @@ import { MemberUnconnectedMockApi } from './apps/member/unconnected/api'; import { MemberCurrentUserMockApi } from './apps/member/current-user/api'; import { MemberPartnerMockApi } from './apps/member/partner/api'; import { MemberPartnerBranchMockApi } from './apps/member/partner-branch/api'; +import { MemberPartnerDivisionMockApi } from './apps/member/partner-division/api'; import { MessagesMockApi } from 'app/mock-api/common/messages/api'; import { NavigationMockApi } from 'app/mock-api/common/navigation/api'; import { NotesMockApi } from 'app/mock-api/apps/notes/api'; @@ -54,6 +55,7 @@ export const mockApiServices = [ MemberCurrentUserMockApi, MemberPartnerMockApi, MemberPartnerBranchMockApi, + MemberPartnerDivisionMockApi, MessagesMockApi, NavigationMockApi, NotesMockApi, diff --git a/src/app/modules/admin/member/partner-division/components/index.ts b/src/app/modules/admin/member/partner-division/components/index.ts new file mode 100644 index 0000000..04759eb --- /dev/null +++ b/src/app/modules/admin/member/partner-division/components/index.ts @@ -0,0 +1,3 @@ +import { ListComponent } from './list.component'; + +export const COMPONENTS = [ListComponent]; diff --git a/src/app/modules/admin/member/partner-division/components/list.component.html b/src/app/modules/admin/member/partner-division/components/list.component.html new file mode 100644 index 0000000..537b2a1 --- /dev/null +++ b/src/app/modules/admin/member/partner-division/components/list.component.html @@ -0,0 +1,365 @@ +
+ +
+ +
+ +
+ +
부본
+ +
+ + + + + + + 40 + 60 + 80 + 100 + + + + + LV.1 + LV.2 + LV.3 + LV.4 + + + + + 정상 + 대기 + 탈퇴 + 휴면 + 블랙 + 정지 + + + + + 카지노제한 + 슬롯제한 + + + + + 계좌입금 + + + + + 카지노콤프 + 슬롯콤프 + 배팅콤프 + 첫충콤프 + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + +
+
+ + +
+ There are no partnerdivisions! +
+
+
+
+
diff --git a/src/app/modules/admin/member/partner-division/components/list.component.ts b/src/app/modules/admin/member/partner-division/components/list.component.ts new file mode 100644 index 0000000..df9254d --- /dev/null +++ b/src/app/modules/admin/member/partner-division/components/list.component.ts @@ -0,0 +1,198 @@ +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + OnDestroy, + OnInit, + ViewChild, + ViewEncapsulation, +} from '@angular/core'; +import { + FormBuilder, + FormControl, + FormGroup, + Validators, +} from '@angular/forms'; +import { MatCheckboxChange } from '@angular/material/checkbox'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { + debounceTime, + map, + merge, + Observable, + Subject, + switchMap, + takeUntil, +} from 'rxjs'; +import { fuseAnimations } from '@fuse/animations'; +import { FuseConfirmationService } from '@fuse/services/confirmation'; + +import { User } from '../../user/models/user'; +import { PartnerDivision } from '../models/partner-division'; +import { PartnerDivisionPagination } from '../models/partner-division-pagination'; +import { PartnerDivisionService } from '../services/Partner-division.service'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'partner-division-list', + templateUrl: './list.component.html', + styles: [ + /* language=SCSS */ + ` + .inventory-grid { + grid-template-columns: 60px auto 40px; + + @screen sm { + grid-template-columns: 60px 60px 60px 60px 60px 60px auto 60px; + } + + @screen md { + grid-template-columns: 60px 60px 60px 60px 60px 60px auto 60px 60px; + } + + @screen lg { + grid-template-columns: 60px 70px 70px 70px 70px 100px 60px 60px auto 60px 60px 60px 60px; + } + } + `, + ], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush, + animations: fuseAnimations, +}) +export class ListComponent implements OnInit, AfterViewInit, OnDestroy { + @ViewChild(MatPaginator) private _paginator!: MatPaginator; + @ViewChild(MatSort) private _sort!: MatSort; + + partnerDivisions$!: Observable; + users$!: Observable; + + isLoading = false; + searchInputControl = new FormControl(); + selectedPartnerDivision?: PartnerDivision; + pagination?: PartnerDivisionPagination; + + private _unsubscribeAll: Subject = new Subject(); + + /** + * Constructor + */ + constructor( + private _changeDetectorRef: ChangeDetectorRef, + private _fuseConfirmationService: FuseConfirmationService, + private _formBuilder: FormBuilder, + private _partnerDivisionService: PartnerDivisionService, + private router: Router + ) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Lifecycle hooks + // ----------------------------------------------------------------------------------------------------- + + /** + * On init + */ + ngOnInit(): void { + // Get the pagination + this._partnerDivisionService.pagination$ + .pipe(takeUntil(this._unsubscribeAll)) + .subscribe((pagination: PartnerDivisionPagination | undefined) => { + // Update the pagination + this.pagination = pagination; + + // Mark for check + this._changeDetectorRef.markForCheck(); + }); + + // Get the products + this.partnerDivisions$ = this._partnerDivisionService.partnerDivisions$; + } + + /** + * After view init + */ + ngAfterViewInit(): void { + if (this._sort && this._paginator) { + // Set the initial sort + this._sort.sort({ + id: 'name', + start: 'asc', + disableClear: true, + }); + + // Mark for check + this._changeDetectorRef.markForCheck(); + + // If the partnerDivision changes the sort order... + this._sort.sortChange + .pipe(takeUntil(this._unsubscribeAll)) + .subscribe(() => { + // Reset back to the first page + this._paginator.pageIndex = 0; + }); + + // Get products if sort or page changes + merge(this._sort.sortChange, this._paginator.page) + .pipe( + switchMap(() => { + this.isLoading = true; + return this._partnerDivisionService.getPartnerDivisions( + this._paginator.pageIndex, + this._paginator.pageSize, + this._sort.active, + this._sort.direction + ); + }), + map(() => { + this.isLoading = false; + }) + ) + .subscribe(); + } + } + + /** + * On destroy + */ + ngOnDestroy(): void { + // Unsubscribe from all subscriptions + this._unsubscribeAll.next(null); + this._unsubscribeAll.complete(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + viewUserDetail(id: string): void { + let url: string = 'member/user/' + id; + this.router.navigateByUrl(url); + } + // ----------------------------------------------------------------------------------------------------- + // @ Private methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Create product + */ + __createProduct(): void {} + + /** + * Toggle product details + * + * @param productId + */ + __toggleDetails(productId: string): void {} + + /** + * Track by function for ngFor loops + * + * @param index + * @param item + */ + __trackByFn(index: number, item: any): any { + return item.id || index; + } +} diff --git a/src/app/modules/admin/member/partner-division/models/partner-division-pagination.ts b/src/app/modules/admin/member/partner-division/models/partner-division-pagination.ts new file mode 100644 index 0000000..6f4a4d7 --- /dev/null +++ b/src/app/modules/admin/member/partner-division/models/partner-division-pagination.ts @@ -0,0 +1,8 @@ +export interface PartnerDivisionPagination { + length: number; + size: number; + page: number; + lastPage: number; + startIndex: number; + endIndex: number; +} diff --git a/src/app/modules/admin/member/partner-division/models/partner-division.ts b/src/app/modules/admin/member/partner-division/models/partner-division.ts new file mode 100644 index 0000000..3b4e0e3 --- /dev/null +++ b/src/app/modules/admin/member/partner-division/models/partner-division.ts @@ -0,0 +1,29 @@ +export interface PartnerDivision { + id?: string; + totalPartnerCount?: number; + totalHoldingMoney?: number; + totalComp?: number; + total?: number; + branchCount?: number; + divisionCount?: number; + officeCount?: number; + storeCount?: number; + memberCount?: number; + nickname?: string; + accountHolder?: string; + phoneNumber?: string; + calculateType?: string; + ownCash?: number; + ownComp?: number; + ownCoupon?: number; + gameMoney?: number; + todayComp?: number; + totalDeposit?: number; + totalWithdraw?: number; + balance?: number; + registDate?: string; + finalSigninDate?: string; + ip?: string; + state?: string; + note?: string; +} diff --git a/src/app/modules/admin/member/partner-division/partner-division.module.ts b/src/app/modules/admin/member/partner-division/partner-division.module.ts new file mode 100644 index 0000000..4f6bb9a --- /dev/null +++ b/src/app/modules/admin/member/partner-division/partner-division.module.ts @@ -0,0 +1,50 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { MatButtonModule } from '@angular/material/button'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatPaginatorModule } from '@angular/material/paginator'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { MatRippleModule } from '@angular/material/core'; +import { MatSortModule } from '@angular/material/sort'; +import { MatSelectModule } from '@angular/material/select'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { MatGridListModule } from '@angular/material/grid-list'; +import { MatSlideToggleModule } from '@angular/material/slide-toggle'; +import { MatRadioModule } from '@angular/material/radio'; +import { MatCheckboxModule } from '@angular/material/checkbox'; + +import { TranslocoModule } from '@ngneat/transloco'; + +import { SharedModule } from 'app/shared/shared.module'; + +import { COMPONENTS } from './components'; + +import { partnerDivisionRoutes } from './partner-division.routing'; + +@NgModule({ + declarations: [COMPONENTS], + imports: [ + TranslocoModule, + SharedModule, + RouterModule.forChild(partnerDivisionRoutes), + + MatButtonModule, + MatFormFieldModule, + MatIconModule, + MatInputModule, + MatPaginatorModule, + MatProgressBarModule, + MatRippleModule, + MatSortModule, + MatSelectModule, + MatTooltipModule, + MatGridListModule, + MatSlideToggleModule, + MatRadioModule, + MatCheckboxModule, + ], +}) +export class PartnerDivisionModule {} diff --git a/src/app/modules/admin/member/partner-division/partner-division.routing.ts b/src/app/modules/admin/member/partner-division/partner-division.routing.ts new file mode 100644 index 0000000..5c68715 --- /dev/null +++ b/src/app/modules/admin/member/partner-division/partner-division.routing.ts @@ -0,0 +1,24 @@ +import { Route } from '@angular/router'; + +import { ListComponent } from './components/list.component'; +import { ViewComponent } from '../user/components/view.component'; + +import { PartnerDivisionsResolver } from './resolvers/partner-division.resolver'; +import { UserResolver } from '../user/resolvers/user.resolver'; + +export const partnerDivisionRoutes: Route[] = [ + { + path: '', + component: ListComponent, + resolve: { + partnerBranchs: PartnerDivisionsResolver, + }, + }, + { + path: ':id', + component: ViewComponent, + resolve: { + users: UserResolver, + }, + }, +]; diff --git a/src/app/modules/admin/member/partner-division/resolvers/partner-division.resolver.ts b/src/app/modules/admin/member/partner-division/resolvers/partner-division.resolver.ts new file mode 100644 index 0000000..adc2aa7 --- /dev/null +++ b/src/app/modules/admin/member/partner-division/resolvers/partner-division.resolver.ts @@ -0,0 +1,89 @@ +import { Injectable } from '@angular/core'; +import { + ActivatedRouteSnapshot, + Resolve, + Router, + RouterStateSnapshot, +} from '@angular/router'; +import { catchError, Observable, throwError } from 'rxjs'; + +import { PartnerDivision } from '../models/partner-division'; +import { PartnerDivisionPagination } from '../models/partner-division-pagination'; +import { PartnerDivisionService } from '../services/Partner-division.service'; + +@Injectable({ + providedIn: 'root', +}) +export class PartnerDivisionResolver implements Resolve { + /** + * Constructor + */ + constructor( + private _partnerDivisionService: PartnerDivisionService, + private _router: Router + ) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Resolver + * + * @param route + * @param state + */ + resolve( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable { + return this._partnerDivisionService + .getPartnerDivisionById(route.paramMap.get('id')) + .pipe( + // Error here means the requested product is not available + catchError((error) => { + // Log the error + console.error(error); + + // Get the parent url + const parentUrl = state.url.split('/').slice(0, -1).join('/'); + + // Navigate to there + this._router.navigateByUrl(parentUrl); + + // Throw an error + return throwError(error); + }) + ); + } +} + +@Injectable({ + providedIn: 'root', +}) +export class PartnerDivisionsResolver implements Resolve { + /** + * Constructor + */ + constructor(private _partnerDivisionService: PartnerDivisionService) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Resolver + * + * @param route + * @param state + */ + resolve( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable<{ + pagination: PartnerDivisionPagination; + partnerDivisions: PartnerDivision[]; + }> { + return this._partnerDivisionService.getPartnerDivisions(); + } +} diff --git a/src/app/modules/admin/member/partner-division/services/Partner-division.service.ts b/src/app/modules/admin/member/partner-division/services/Partner-division.service.ts new file mode 100644 index 0000000..f410aac --- /dev/null +++ b/src/app/modules/admin/member/partner-division/services/Partner-division.service.ts @@ -0,0 +1,161 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { + BehaviorSubject, + filter, + map, + Observable, + of, + switchMap, + take, + tap, + throwError, +} from 'rxjs'; + +import { PartnerDivision } from '../models/partner-division'; +import { PartnerDivisionPagination } from '../models/partner-division-pagination'; + +@Injectable({ + providedIn: 'root', +}) +export class PartnerDivisionService { + // Private + private __pagination = new BehaviorSubject< + PartnerDivisionPagination | undefined + >(undefined); + private __partnerDivision = new BehaviorSubject( + undefined + ); + private __partnerDivisions = new BehaviorSubject< + PartnerDivision[] | undefined + >(undefined); + + /** + * Constructor + */ + constructor(private _httpClient: HttpClient) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Accessors + // ----------------------------------------------------------------------------------------------------- + + /** + * Getter for pagination + */ + get pagination$(): Observable { + return this.__pagination.asObservable(); + } + + /** + * Getter for partnerDivision + */ + get partnerDivision$(): Observable { + return this.__partnerDivision.asObservable(); + } + + /** + * Getter for partnerDivisions + */ + get partnerDivisions$(): Observable { + return this.__partnerDivisions.asObservable(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Get partnerDivisions + * + * + * @param page + * @param size + * @param sort + * @param order + * @param search + */ + getPartnerDivisions( + page: number = 0, + size: number = 10, + sort: string = 'name', + order: 'asc' | 'desc' | '' = 'asc', + search: string = '' + ): Observable<{ + pagination: PartnerDivisionPagination; + partnerDivisions: PartnerDivision[]; + }> { + return this._httpClient + .get<{ + pagination: PartnerDivisionPagination; + partnerDivisions: PartnerDivision[]; + }>('api/apps/member/partner-division/partner-divisions', { + params: { + page: '' + page, + size: '' + size, + sort, + order, + search, + }, + }) + .pipe( + tap((response) => { + this.__pagination.next(response.pagination); + this.__partnerDivisions.next(response.partnerDivisions); + }) + ); + } + + /** + * Get product by id + */ + getPartnerDivisionById(id: string | null): Observable { + return this.__partnerDivisions.pipe( + take(1), + map((partnerDivisions) => { + // Find the product + const partnerDivision = + partnerDivisions?.find((item) => item.id === id) || undefined; + + // Update the product + this.__partnerDivision.next(partnerDivision); + + // Return the product + return partnerDivision; + }), + switchMap((product) => { + if (!product) { + return throwError('Could not found product with id of ' + id + '!'); + } + + return of(product); + }) + ); + } + + /** + * Create product + */ + createPartnerDivision(): Observable { + return this.partnerDivisions$.pipe( + take(1), + switchMap((partnerDivisions) => + this._httpClient + .post('api/apps/member/partner-division/product', {}) + .pipe( + map((newPartnerDivision) => { + // Update the partnerDivisions with the new product + if (!!partnerDivisions) { + this.__partnerDivisions.next([ + newPartnerDivision, + ...partnerDivisions, + ]); + } + + // Return the new product + return newPartnerDivision; + }) + ) + ) + ); + } +} diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 712affa..13d3eea 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -8,6 +8,7 @@ "Project": "Project", "All Partner": "All Partner", "Partner Branch": "Partner Branch", + "Partner Division": "Partner Division", "Mainoffice": "Mainoffice", "Analytics": "Analytics", "Deposit": "Deposit", diff --git a/src/assets/i18n/ko.json b/src/assets/i18n/ko.json index 413193c..d017bed 100644 --- a/src/assets/i18n/ko.json +++ b/src/assets/i18n/ko.json @@ -7,7 +7,8 @@ "Unconnected": "장기미접속회원", "Project": "프로젝트", "All Partner": "전체파트너", - "Partner Branch": "부본", + "Partner Branch": "대본", + "Partner Division": "부본", "Analytics": "Analytics", "Deposit": "입금관리", "Withdraw": "출금관리", From 3f559c1de5c487a94a3ba982757a549d1631caec Mon Sep 17 00:00:00 2001 From: JUNG YI DAM Date: Wed, 13 Jul 2022 02:10:43 +0000 Subject: [PATCH 6/8] =?UTF-8?q?=ED=8C=8C=ED=8A=B8=EB=84=88=20=EB=B3=B8?= =?UTF-8?q?=EC=82=AC=20page=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.routing.ts | 7 + .../apps/member/partner-mainoffice/api.ts | 228 +++++++++++ .../apps/member/partner-mainoffice/data.ts | 33 ++ src/app/mock-api/common/navigation/data.ts | 7 + .../components/list.component.ts | 2 +- .../resolvers/partner-branch.resolver.ts | 2 +- ...h.service.ts => partner-branch.service.ts} | 0 .../components/list.component.ts | 2 +- .../resolvers/partner-division.resolver.ts | 2 +- ...service.ts => partner-division.service.ts} | 0 .../partner-mainoffice/components/index.ts | 3 + .../components/list.component.html | 367 ++++++++++++++++++ .../components/list.component.ts | 199 ++++++++++ .../models/partner-mainoffice-pagination.ts | 8 + .../models/partner-mainoffice.ts | 29 ++ .../partner-mainoffice.module.ts | 50 +++ .../partner-mainoffice.routing.ts | 24 ++ .../resolvers/partner-mainoffice.resolver.ts | 89 +++++ .../services/partner-mainoffice.service.ts | 164 ++++++++ src/assets/i18n/en.json | 1 + src/assets/i18n/ko.json | 1 + 21 files changed, 1214 insertions(+), 4 deletions(-) create mode 100644 src/app/mock-api/apps/member/partner-mainoffice/api.ts create mode 100644 src/app/mock-api/apps/member/partner-mainoffice/data.ts rename src/app/modules/admin/member/partner-branch/services/{Partner-branch.service.ts => partner-branch.service.ts} (100%) rename src/app/modules/admin/member/partner-division/services/{Partner-division.service.ts => partner-division.service.ts} (100%) create mode 100644 src/app/modules/admin/member/partner-mainoffice/components/index.ts create mode 100644 src/app/modules/admin/member/partner-mainoffice/components/list.component.html create mode 100644 src/app/modules/admin/member/partner-mainoffice/components/list.component.ts create mode 100644 src/app/modules/admin/member/partner-mainoffice/models/partner-mainoffice-pagination.ts create mode 100644 src/app/modules/admin/member/partner-mainoffice/models/partner-mainoffice.ts create mode 100644 src/app/modules/admin/member/partner-mainoffice/partner-mainoffice.module.ts create mode 100644 src/app/modules/admin/member/partner-mainoffice/partner-mainoffice.routing.ts create mode 100644 src/app/modules/admin/member/partner-mainoffice/resolvers/partner-mainoffice.resolver.ts create mode 100644 src/app/modules/admin/member/partner-mainoffice/services/partner-mainoffice.service.ts diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts index 7d3aa7e..6c05664 100644 --- a/src/app/app.routing.ts +++ b/src/app/app.routing.ts @@ -178,6 +178,13 @@ export const appRoutes: Route[] = [ (m: any) => m.PartnerModule ), }, + { + path: 'partner-mainoffice', + loadChildren: () => + import( + 'app/modules/admin/member/partner-mainoffice/partner-mainoffice.module' + ).then((m: any) => m.PartnerMainofficeModule), + }, { path: 'partner-branch', loadChildren: () => diff --git a/src/app/mock-api/apps/member/partner-mainoffice/api.ts b/src/app/mock-api/apps/member/partner-mainoffice/api.ts new file mode 100644 index 0000000..86a96dd --- /dev/null +++ b/src/app/mock-api/apps/member/partner-mainoffice/api.ts @@ -0,0 +1,228 @@ +import { Injectable } from '@angular/core'; +import { assign, cloneDeep } from 'lodash-es'; +import { FuseMockApiService, FuseMockApiUtils } from '@fuse/lib/mock-api'; +import { partnerMainoffices as partnerMainofficesData } from './data'; + +@Injectable({ + providedIn: 'root', +}) +export class MemberPartnerMainofficeMockApi { + private _partnerMainoffices: any[] = partnerMainofficesData; + + /** + * Constructor + */ + constructor(private _fuseMockApiService: FuseMockApiService) { + // Register Mock API handlers + this.registerHandlers(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Register Mock API handlers + */ + registerHandlers(): void { + // ----------------------------------------------------------------------------------------------------- + // @ PartnerMainoffices - GET + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onGet('api/apps/member/partner-mainoffice/partner-mainoffices', 300) + .reply(({ request }) => { + // Get available queries + const search = request.params.get('search'); + const sort = request.params.get('sort') || 'name'; + const order = request.params.get('order') || 'asc'; + const page = parseInt(request.params.get('page') ?? '1', 10); + const size = parseInt(request.params.get('size') ?? '10', 10); + + // Clone the partnerMainoffices + let partnerMainoffices: any[] | null = cloneDeep( + this._partnerMainoffices + ); + + // Sort the partnerMainoffices + if (sort === 'sku' || sort === 'name' || sort === 'active') { + partnerMainoffices.sort((a, b) => { + const fieldA = a[sort].toString().toUpperCase(); + const fieldB = b[sort].toString().toUpperCase(); + return order === 'asc' + ? fieldA.localeCompare(fieldB) + : fieldB.localeCompare(fieldA); + }); + } else { + partnerMainoffices.sort((a, b) => + order === 'asc' ? a[sort] - b[sort] : b[sort] - a[sort] + ); + } + + // If search exists... + if (search) { + // Filter the partnerMainoffices + partnerMainoffices = partnerMainoffices.filter( + (contact: any) => + contact.name && + contact.name.toLowerCase().includes(search.toLowerCase()) + ); + } + + // Paginate - Start + const partnerMainofficesLength = partnerMainoffices.length; + + // Calculate pagination details + const begin = page * size; + const end = Math.min(size * (page + 1), partnerMainofficesLength); + const lastPage = Math.max( + Math.ceil(partnerMainofficesLength / size), + 1 + ); + + // Prepare the pagination object + let pagination = {}; + + // If the requested page number is bigger than + // the last possible page number, return null for + // partnerMainoffices but also send the last possible page so + // the app can navigate to there + if (page > lastPage) { + partnerMainoffices = null; + pagination = { + lastPage, + }; + } else { + // Paginate the results by size + partnerMainoffices = partnerMainoffices.slice(begin, end); + + // Prepare the pagination mock-api + pagination = { + length: partnerMainofficesLength, + size: size, + page: page, + lastPage: lastPage, + startIndex: begin, + endIndex: end - 1, + }; + } + + // Return the response + return [ + 200, + { + partnerMainoffices, + pagination, + }, + ]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerMainoffice - GET + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onGet('api/apps/member/partne-mainoffice/partner-mainoffice') + .reply(({ request }) => { + // Get the id from the params + const id = request.params.get('id'); + + // Clone the partnerMainoffices + const partnerMainoffices = cloneDeep(this._partnerMainoffices); + + // Find the partnerMainoffice + const partnerMainoffice = partnerMainoffices.find( + (item: any) => item.id === id + ); + + // Return the response + return [200, partnerMainoffice]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerMainoffice - POST + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onPost('api/apps/member/partner-mainoffice/partner-mainoffice') + .reply(() => { + // Generate a new partnerMainoffice + const newPartnerMainoffice = { + id: FuseMockApiUtils.guid(), + category: '', + name: 'A New User', + description: '', + tags: [], + sku: '', + barcode: '', + brand: '', + vendor: '', + stock: '', + reserved: '', + cost: '', + basePrice: '', + taxPercent: '', + price: '', + weight: '', + thumbnail: '', + images: [], + active: false, + }; + + // Unshift the new partnerMainoffice + this._partnerMainoffices.unshift(newPartnerMainoffice); + + // Return the response + return [200, newPartnerMainoffice]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerMainoffice - PATCH + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onPatch('api/apps/member/partner-mainoffice/partner-mainoffice') + .reply(({ request }) => { + // Get the id and partnerMainoffice + const id = request.body.id; + const partnerMainoffice = cloneDeep(request.body.partnerMainoffice); + + // Prepare the updated partnerMainoffice + let updatedPartnerMainoffice = null; + + // Find the partnerMainoffice and update it + this._partnerMainoffices.forEach((item, index, partnerMainoffices) => { + if (item.id === id) { + // Update the partnerMainoffice + partnerMainoffices[index] = assign( + {}, + partnerMainoffices[index], + partnerMainoffice + ); + + // Store the updated partnerMainoffice + updatedPartnerMainoffice = partnerMainoffices[index]; + } + }); + + // Return the response + return [200, updatedPartnerMainoffice]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerMainoffice - DELETE + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onDelete('api/apps/member/partner-mainoffice/partner-mainoffice') + .reply(({ request }) => { + // Get the id + const id = request.params.get('id'); + + // Find the partnerMainoffice and delete it + this._partnerMainoffices.forEach((item, index) => { + if (item.id === id) { + this._partnerMainoffices.splice(index, 1); + } + }); + + // Return the response + return [200, true]; + }); + } +} diff --git a/src/app/mock-api/apps/member/partner-mainoffice/data.ts b/src/app/mock-api/apps/member/partner-mainoffice/data.ts new file mode 100644 index 0000000..9ae712c --- /dev/null +++ b/src/app/mock-api/apps/member/partner-mainoffice/data.ts @@ -0,0 +1,33 @@ +/* eslint-disable */ + +export const partnerMainoffices = [ + { + id: 'on00', + totalPartnerCount: '5', + totalHoldingMoney: 303675, + totalComp: 108933, + total: 412608, + branchCount: 1, + divisionCount: 1, + officeCount: 1, + storeCount: 1, + memberCount: 1, + nickname: 'on00', + accountHolder: '11', + phoneNumber: '010-1111-1111', + calculateType: '롤링', + ownCash: 50000, + ownComp: 1711, + ownCoupon: 50000, + gameMoney: 0, + todayComp: 0, + totalDeposit: 0, + totalWithdraw: 0, + balance: 0, + registDate: '2022-06-12 15:38', + finalSigninDate: '', + ip: '', + state: '정상', + note: '대본등록', + }, +]; diff --git a/src/app/mock-api/common/navigation/data.ts b/src/app/mock-api/common/navigation/data.ts index 321e086..51055d0 100644 --- a/src/app/mock-api/common/navigation/data.ts +++ b/src/app/mock-api/common/navigation/data.ts @@ -74,6 +74,13 @@ export const defaultNavigation: FuseNavigationItem[] = [ icon: 'heroicons_outline:academic-cap', link: '/member/partner', }, + { + id: 'member.partner-mainoffice', + title: 'Partner Mainoffice', + type: 'basic', + icon: 'heroicons_outline:academic-cap', + link: '/member/partner-mainoffice', + }, { id: 'member.partner-branch', title: 'Partner Branch', diff --git a/src/app/modules/admin/member/partner-branch/components/list.component.ts b/src/app/modules/admin/member/partner-branch/components/list.component.ts index 8bd1f17..4b19317 100644 --- a/src/app/modules/admin/member/partner-branch/components/list.component.ts +++ b/src/app/modules/admin/member/partner-branch/components/list.component.ts @@ -32,7 +32,7 @@ import { FuseConfirmationService } from '@fuse/services/confirmation'; import { User } from '../../user/models/user'; import { PartnerBranch } from '../models/partner-branch'; import { PartnerBranchPagination } from '../models/partner-branch-pagination'; -import { PartnerBranchService } from '../services/Partner-branch.service'; +import { PartnerBranchService } from '../services/partner-branch.service'; import { Router } from '@angular/router'; @Component({ diff --git a/src/app/modules/admin/member/partner-branch/resolvers/partner-branch.resolver.ts b/src/app/modules/admin/member/partner-branch/resolvers/partner-branch.resolver.ts index fd237e8..4820978 100644 --- a/src/app/modules/admin/member/partner-branch/resolvers/partner-branch.resolver.ts +++ b/src/app/modules/admin/member/partner-branch/resolvers/partner-branch.resolver.ts @@ -9,7 +9,7 @@ import { catchError, Observable, throwError } from 'rxjs'; import { PartnerBranch } from '../models/partner-branch'; import { PartnerBranchPagination } from '../models/partner-branch-pagination'; -import { PartnerBranchService } from '../services/Partner-branch.service'; +import { PartnerBranchService } from '../services/partner-branch.service'; @Injectable({ providedIn: 'root', diff --git a/src/app/modules/admin/member/partner-branch/services/Partner-branch.service.ts b/src/app/modules/admin/member/partner-branch/services/partner-branch.service.ts similarity index 100% rename from src/app/modules/admin/member/partner-branch/services/Partner-branch.service.ts rename to src/app/modules/admin/member/partner-branch/services/partner-branch.service.ts diff --git a/src/app/modules/admin/member/partner-division/components/list.component.ts b/src/app/modules/admin/member/partner-division/components/list.component.ts index df9254d..f25e631 100644 --- a/src/app/modules/admin/member/partner-division/components/list.component.ts +++ b/src/app/modules/admin/member/partner-division/components/list.component.ts @@ -32,7 +32,7 @@ import { FuseConfirmationService } from '@fuse/services/confirmation'; import { User } from '../../user/models/user'; import { PartnerDivision } from '../models/partner-division'; import { PartnerDivisionPagination } from '../models/partner-division-pagination'; -import { PartnerDivisionService } from '../services/Partner-division.service'; +import { PartnerDivisionService } from '../services/partner-division.service'; import { Router } from '@angular/router'; @Component({ diff --git a/src/app/modules/admin/member/partner-division/resolvers/partner-division.resolver.ts b/src/app/modules/admin/member/partner-division/resolvers/partner-division.resolver.ts index adc2aa7..14568cb 100644 --- a/src/app/modules/admin/member/partner-division/resolvers/partner-division.resolver.ts +++ b/src/app/modules/admin/member/partner-division/resolvers/partner-division.resolver.ts @@ -9,7 +9,7 @@ import { catchError, Observable, throwError } from 'rxjs'; import { PartnerDivision } from '../models/partner-division'; import { PartnerDivisionPagination } from '../models/partner-division-pagination'; -import { PartnerDivisionService } from '../services/Partner-division.service'; +import { PartnerDivisionService } from '../services/partner-division.service'; @Injectable({ providedIn: 'root', diff --git a/src/app/modules/admin/member/partner-division/services/Partner-division.service.ts b/src/app/modules/admin/member/partner-division/services/partner-division.service.ts similarity index 100% rename from src/app/modules/admin/member/partner-division/services/Partner-division.service.ts rename to src/app/modules/admin/member/partner-division/services/partner-division.service.ts diff --git a/src/app/modules/admin/member/partner-mainoffice/components/index.ts b/src/app/modules/admin/member/partner-mainoffice/components/index.ts new file mode 100644 index 0000000..04759eb --- /dev/null +++ b/src/app/modules/admin/member/partner-mainoffice/components/index.ts @@ -0,0 +1,3 @@ +import { ListComponent } from './list.component'; + +export const COMPONENTS = [ListComponent]; diff --git a/src/app/modules/admin/member/partner-mainoffice/components/list.component.html b/src/app/modules/admin/member/partner-mainoffice/components/list.component.html new file mode 100644 index 0000000..241793f --- /dev/null +++ b/src/app/modules/admin/member/partner-mainoffice/components/list.component.html @@ -0,0 +1,367 @@ +
+ +
+ +
+ +
+ +
대본
+ +
+ + + + + + + 40 + 60 + 80 + 100 + + + + + LV.1 + LV.2 + LV.3 + LV.4 + + + + + 정상 + 대기 + 탈퇴 + 휴면 + 블랙 + 정지 + + + + + 카지노제한 + 슬롯제한 + + + + + 계좌입금 + + + + + 카지노콤프 + 슬롯콤프 + 배팅콤프 + 첫충콤프 + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + +
+
+ + +
+ There are no partner mainoffices! +
+
+
+
+
diff --git a/src/app/modules/admin/member/partner-mainoffice/components/list.component.ts b/src/app/modules/admin/member/partner-mainoffice/components/list.component.ts new file mode 100644 index 0000000..3518102 --- /dev/null +++ b/src/app/modules/admin/member/partner-mainoffice/components/list.component.ts @@ -0,0 +1,199 @@ +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + OnDestroy, + OnInit, + ViewChild, + ViewEncapsulation, +} from '@angular/core'; +import { + FormBuilder, + FormControl, + FormGroup, + Validators, +} from '@angular/forms'; +import { MatCheckboxChange } from '@angular/material/checkbox'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { + debounceTime, + map, + merge, + Observable, + Subject, + switchMap, + takeUntil, +} from 'rxjs'; +import { fuseAnimations } from '@fuse/animations'; +import { FuseConfirmationService } from '@fuse/services/confirmation'; + +import { User } from '../../user/models/user'; +import { PartnerMainoffice } from '../models/partner-mainoffice'; +import { PartnerMainofficePagination } from '../models/partner-mainoffice-pagination'; +import { PartnerMainofficeService } from '../services/partner-mainoffice.service'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'partner-mainoffice-list', + templateUrl: './list.component.html', + styles: [ + /* language=SCSS */ + ` + .inventory-grid { + grid-template-columns: 60px auto 40px; + + @screen sm { + grid-template-columns: 60px 60px 60px 60px 60px 60px auto 60px; + } + + @screen md { + grid-template-columns: 60px 60px 60px 60px 60px 60px auto 60px 60px; + } + + @screen lg { + grid-template-columns: 60px 70px 70px 70px 70px 100px 60px 60px auto 60px 60px 60px 60px; + } + } + `, + ], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush, + animations: fuseAnimations, +}) +export class ListComponent implements OnInit, AfterViewInit, OnDestroy { + @ViewChild(MatPaginator) private _paginator!: MatPaginator; + @ViewChild(MatSort) private _sort!: MatSort; + + partnerMainoffices$!: Observable; + users$!: Observable; + + isLoading = false; + searchInputControl = new FormControl(); + selectedPartnerMainoffice?: PartnerMainoffice; + pagination?: PartnerMainofficePagination; + + private _unsubscribeAll: Subject = new Subject(); + + /** + * Constructor + */ + constructor( + private _changeDetectorRef: ChangeDetectorRef, + private _fuseConfirmationService: FuseConfirmationService, + private _formBuilder: FormBuilder, + private _partnerMainofficeService: PartnerMainofficeService, + private router: Router + ) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Lifecycle hooks + // ----------------------------------------------------------------------------------------------------- + + /** + * On init + */ + ngOnInit(): void { + // Get the pagination + this._partnerMainofficeService.pagination$ + .pipe(takeUntil(this._unsubscribeAll)) + .subscribe((pagination: PartnerMainofficePagination | undefined) => { + // Update the pagination + this.pagination = pagination; + + // Mark for check + this._changeDetectorRef.markForCheck(); + }); + + // Get the products + this.partnerMainoffices$ = + this._partnerMainofficeService.partnerMainoffices$; + } + + /** + * After view init + */ + ngAfterViewInit(): void { + if (this._sort && this._paginator) { + // Set the initial sort + this._sort.sort({ + id: 'name', + start: 'asc', + disableClear: true, + }); + + // Mark for check + this._changeDetectorRef.markForCheck(); + + // If the partnerMainoffice changes the sort order... + this._sort.sortChange + .pipe(takeUntil(this._unsubscribeAll)) + .subscribe(() => { + // Reset back to the first page + this._paginator.pageIndex = 0; + }); + + // Get products if sort or page changes + merge(this._sort.sortChange, this._paginator.page) + .pipe( + switchMap(() => { + this.isLoading = true; + return this._partnerMainofficeService.getPartnerMainoffices( + this._paginator.pageIndex, + this._paginator.pageSize, + this._sort.active, + this._sort.direction + ); + }), + map(() => { + this.isLoading = false; + }) + ) + .subscribe(); + } + } + + /** + * On destroy + */ + ngOnDestroy(): void { + // Unsubscribe from all subscriptions + this._unsubscribeAll.next(null); + this._unsubscribeAll.complete(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + viewUserDetail(id: string): void { + let url: string = 'member/user/' + id; + this.router.navigateByUrl(url); + } + // ----------------------------------------------------------------------------------------------------- + // @ Private methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Create product + */ + __createProduct(): void {} + + /** + * Toggle product details + * + * @param productId + */ + __toggleDetails(productId: string): void {} + + /** + * Track by function for ngFor loops + * + * @param index + * @param item + */ + __trackByFn(index: number, item: any): any { + return item.id || index; + } +} diff --git a/src/app/modules/admin/member/partner-mainoffice/models/partner-mainoffice-pagination.ts b/src/app/modules/admin/member/partner-mainoffice/models/partner-mainoffice-pagination.ts new file mode 100644 index 0000000..706486d --- /dev/null +++ b/src/app/modules/admin/member/partner-mainoffice/models/partner-mainoffice-pagination.ts @@ -0,0 +1,8 @@ +export interface PartnerMainofficePagination { + length: number; + size: number; + page: number; + lastPage: number; + startIndex: number; + endIndex: number; +} diff --git a/src/app/modules/admin/member/partner-mainoffice/models/partner-mainoffice.ts b/src/app/modules/admin/member/partner-mainoffice/models/partner-mainoffice.ts new file mode 100644 index 0000000..4c55d7f --- /dev/null +++ b/src/app/modules/admin/member/partner-mainoffice/models/partner-mainoffice.ts @@ -0,0 +1,29 @@ +export interface PartnerMainoffice { + id?: string; + totalPartnerCount?: number; + totalHoldingMoney?: number; + totalComp?: number; + total?: number; + branchCount?: number; + divisionCount?: number; + officeCount?: number; + storeCount?: number; + memberCount?: number; + nickname?: string; + accountHolder?: string; + phoneNumber?: string; + calculateType?: string; + ownCash?: number; + ownComp?: number; + ownCoupon?: number; + gameMoney?: number; + todayComp?: number; + totalDeposit?: number; + totalWithdraw?: number; + balance?: number; + registDate?: string; + finalSigninDate?: string; + ip?: string; + state?: string; + note?: string; +} diff --git a/src/app/modules/admin/member/partner-mainoffice/partner-mainoffice.module.ts b/src/app/modules/admin/member/partner-mainoffice/partner-mainoffice.module.ts new file mode 100644 index 0000000..981d691 --- /dev/null +++ b/src/app/modules/admin/member/partner-mainoffice/partner-mainoffice.module.ts @@ -0,0 +1,50 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { MatButtonModule } from '@angular/material/button'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatPaginatorModule } from '@angular/material/paginator'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { MatRippleModule } from '@angular/material/core'; +import { MatSortModule } from '@angular/material/sort'; +import { MatSelectModule } from '@angular/material/select'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { MatGridListModule } from '@angular/material/grid-list'; +import { MatSlideToggleModule } from '@angular/material/slide-toggle'; +import { MatRadioModule } from '@angular/material/radio'; +import { MatCheckboxModule } from '@angular/material/checkbox'; + +import { TranslocoModule } from '@ngneat/transloco'; + +import { SharedModule } from 'app/shared/shared.module'; + +import { COMPONENTS } from './components'; + +import { partnerMainofficeRoutes } from './partner-mainoffice.routing'; + +@NgModule({ + declarations: [COMPONENTS], + imports: [ + TranslocoModule, + SharedModule, + RouterModule.forChild(partnerMainofficeRoutes), + + MatButtonModule, + MatFormFieldModule, + MatIconModule, + MatInputModule, + MatPaginatorModule, + MatProgressBarModule, + MatRippleModule, + MatSortModule, + MatSelectModule, + MatTooltipModule, + MatGridListModule, + MatSlideToggleModule, + MatRadioModule, + MatCheckboxModule, + ], +}) +export class PartnerMainofficeModule {} diff --git a/src/app/modules/admin/member/partner-mainoffice/partner-mainoffice.routing.ts b/src/app/modules/admin/member/partner-mainoffice/partner-mainoffice.routing.ts new file mode 100644 index 0000000..f05575e --- /dev/null +++ b/src/app/modules/admin/member/partner-mainoffice/partner-mainoffice.routing.ts @@ -0,0 +1,24 @@ +import { Route } from '@angular/router'; + +import { ListComponent } from './components/list.component'; +import { ViewComponent } from '../user/components/view.component'; + +import { PartnerMainofficesResolver } from './resolvers/partner-mainoffice.resolver'; +import { UserResolver } from '../user/resolvers/user.resolver'; + +export const partnerMainofficeRoutes: Route[] = [ + { + path: '', + component: ListComponent, + resolve: { + partnerMainoffices: PartnerMainofficesResolver, + }, + }, + { + path: ':id', + component: ViewComponent, + resolve: { + users: UserResolver, + }, + }, +]; diff --git a/src/app/modules/admin/member/partner-mainoffice/resolvers/partner-mainoffice.resolver.ts b/src/app/modules/admin/member/partner-mainoffice/resolvers/partner-mainoffice.resolver.ts new file mode 100644 index 0000000..15919d7 --- /dev/null +++ b/src/app/modules/admin/member/partner-mainoffice/resolvers/partner-mainoffice.resolver.ts @@ -0,0 +1,89 @@ +import { Injectable } from '@angular/core'; +import { + ActivatedRouteSnapshot, + Resolve, + Router, + RouterStateSnapshot, +} from '@angular/router'; +import { catchError, Observable, throwError } from 'rxjs'; + +import { PartnerMainoffice } from '../models/partner-mainoffice'; +import { PartnerMainofficePagination } from '../models/partner-mainoffice-pagination'; +import { PartnerMainofficeService } from '../services/partner-mainoffice.service'; + +@Injectable({ + providedIn: 'root', +}) +export class PartnerMainofficeResolver implements Resolve { + /** + * Constructor + */ + constructor( + private _partnerMainofficeService: PartnerMainofficeService, + private _router: Router + ) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Resolver + * + * @param route + * @param state + */ + resolve( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable { + return this._partnerMainofficeService + .getPartnerMainofficeById(route.paramMap.get('id')) + .pipe( + // Error here means the requested product is not available + catchError((error) => { + // Log the error + console.error(error); + + // Get the parent url + const parentUrl = state.url.split('/').slice(0, -1).join('/'); + + // Navigate to there + this._router.navigateByUrl(parentUrl); + + // Throw an error + return throwError(error); + }) + ); + } +} + +@Injectable({ + providedIn: 'root', +}) +export class PartnerMainofficesResolver implements Resolve { + /** + * Constructor + */ + constructor(private _partnerMainofficeService: PartnerMainofficeService) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Resolver + * + * @param route + * @param state + */ + resolve( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable<{ + pagination: PartnerMainofficePagination; + partnerMainoffices: PartnerMainoffice[]; + }> { + return this._partnerMainofficeService.getPartnerMainoffices(); + } +} diff --git a/src/app/modules/admin/member/partner-mainoffice/services/partner-mainoffice.service.ts b/src/app/modules/admin/member/partner-mainoffice/services/partner-mainoffice.service.ts new file mode 100644 index 0000000..43188ee --- /dev/null +++ b/src/app/modules/admin/member/partner-mainoffice/services/partner-mainoffice.service.ts @@ -0,0 +1,164 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { + BehaviorSubject, + filter, + map, + Observable, + of, + switchMap, + take, + tap, + throwError, +} from 'rxjs'; + +import { PartnerMainoffice } from '../models/partner-mainoffice'; +import { PartnerMainofficePagination } from '../models/partner-mainoffice-pagination'; + +@Injectable({ + providedIn: 'root', +}) +export class PartnerMainofficeService { + // Private + private __pagination = new BehaviorSubject< + PartnerMainofficePagination | undefined + >(undefined); + private __partnerMainoffice = new BehaviorSubject< + PartnerMainoffice | undefined + >(undefined); + private __partnerMainoffices = new BehaviorSubject< + PartnerMainoffice[] | undefined + >(undefined); + + /** + * Constructor + */ + constructor(private _httpClient: HttpClient) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Accessors + // ----------------------------------------------------------------------------------------------------- + + /** + * Getter for pagination + */ + get pagination$(): Observable { + return this.__pagination.asObservable(); + } + + /** + * Getter for partnerMainoffice + */ + get partnerMainoffice$(): Observable { + return this.__partnerMainoffice.asObservable(); + } + + /** + * Getter for partnerMainoffices + */ + get partnerMainoffices$(): Observable { + return this.__partnerMainoffices.asObservable(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Get partnerMainoffices + * + * + * @param page + * @param size + * @param sort + * @param order + * @param search + */ + getPartnerMainoffices( + page: number = 0, + size: number = 10, + sort: string = 'name', + order: 'asc' | 'desc' | '' = 'asc', + search: string = '' + ): Observable<{ + pagination: PartnerMainofficePagination; + partnerMainoffices: PartnerMainoffice[]; + }> { + return this._httpClient + .get<{ + pagination: PartnerMainofficePagination; + partnerMainoffices: PartnerMainoffice[]; + }>('api/apps/member/partner-mainoffice/partner-mainoffices', { + params: { + page: '' + page, + size: '' + size, + sort, + order, + search, + }, + }) + .pipe( + tap((response) => { + this.__pagination.next(response.pagination); + this.__partnerMainoffices.next(response.partnerMainoffices); + }) + ); + } + + /** + * Get product by id + */ + getPartnerMainofficeById(id: string | null): Observable { + return this.__partnerMainoffices.pipe( + take(1), + map((partnerMainoffices) => { + // Find the product + const partnerMainoffice = + partnerMainoffices?.find((item) => item.id === id) || undefined; + + // Update the product + this.__partnerMainoffice.next(partnerMainoffice); + + // Return the product + return partnerMainoffice; + }), + switchMap((product) => { + if (!product) { + return throwError('Could not found product with id of ' + id + '!'); + } + + return of(product); + }) + ); + } + + /** + * Create product + */ + createPartnerMainoffice(): Observable { + return this.partnerMainoffices$.pipe( + take(1), + switchMap((partnerMainoffices) => + this._httpClient + .post( + 'api/apps/member/partner-mainoffice/product', + {} + ) + .pipe( + map((newPartnerMainoffice) => { + // Update the partnerMainoffices with the new product + if (!!partnerMainoffices) { + this.__partnerMainoffices.next([ + newPartnerMainoffice, + ...partnerMainoffices, + ]); + } + + // Return the new product + return newPartnerMainoffice; + }) + ) + ) + ); + } +} diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 13d3eea..a4a3279 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -7,6 +7,7 @@ "Unconnected": "Unconnected", "Project": "Project", "All Partner": "All Partner", + "Partner Mainoffice": "Partner Mainoffice", "Partner Branch": "Partner Branch", "Partner Division": "Partner Division", "Mainoffice": "Mainoffice", diff --git a/src/assets/i18n/ko.json b/src/assets/i18n/ko.json index d017bed..f67e407 100644 --- a/src/assets/i18n/ko.json +++ b/src/assets/i18n/ko.json @@ -7,6 +7,7 @@ "Unconnected": "장기미접속회원", "Project": "프로젝트", "All Partner": "전체파트너", + "Partner Mainoffice": "본사", "Partner Branch": "대본", "Partner Division": "부본", "Analytics": "Analytics", From 7734a4585ee9bdee3f21d06269e6d0dbf3996d41 Mon Sep 17 00:00:00 2001 From: JUNG YI DAM Date: Wed, 13 Jul 2022 02:14:58 +0000 Subject: [PATCH 7/8] bug fix --- src/app/mock-api/apps/member/partner-branch/data.ts | 2 +- src/app/mock-api/apps/member/partner-division/data.ts | 2 +- .../admin/member/partner-branch/components/list.component.html | 2 +- .../member/partner-division/components/list.component.html | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/mock-api/apps/member/partner-branch/data.ts b/src/app/mock-api/apps/member/partner-branch/data.ts index a75a4ba..2af1fba 100644 --- a/src/app/mock-api/apps/member/partner-branch/data.ts +++ b/src/app/mock-api/apps/member/partner-branch/data.ts @@ -28,6 +28,6 @@ export const partnerBranchs = [ finalSigninDate: '', ip: '', state: '정상', - note: '대본등록', + note: '부본등록', }, ]; diff --git a/src/app/mock-api/apps/member/partner-division/data.ts b/src/app/mock-api/apps/member/partner-division/data.ts index e8373d4..d5af3d0 100644 --- a/src/app/mock-api/apps/member/partner-division/data.ts +++ b/src/app/mock-api/apps/member/partner-division/data.ts @@ -28,6 +28,6 @@ export const partnerDivisions = [ finalSigninDate: '', ip: '', state: '정상', - note: '대본등록', + note: '총판등록', }, ]; diff --git a/src/app/modules/admin/member/partner-branch/components/list.component.html b/src/app/modules/admin/member/partner-branch/components/list.component.html index ff464c3..1a04a5e 100644 --- a/src/app/modules/admin/member/partner-branch/components/list.component.html +++ b/src/app/modules/admin/member/partner-branch/components/list.component.html @@ -331,7 +331,7 @@ diff --git a/src/app/modules/admin/member/partner-division/components/list.component.html b/src/app/modules/admin/member/partner-division/components/list.component.html index 537b2a1..a70e83c 100644 --- a/src/app/modules/admin/member/partner-division/components/list.component.html +++ b/src/app/modules/admin/member/partner-division/components/list.component.html @@ -333,7 +333,7 @@ From 64eda57ac7c8b99e7e8d5cce4bc7680449fc5cd8 Mon Sep 17 00:00:00 2001 From: JUNG YI DAM Date: Wed, 13 Jul 2022 02:28:19 +0000 Subject: [PATCH 8/8] =?UTF-8?q?=ED=8C=8C=ED=8A=B8=EB=84=88=20=EC=B4=9D?= =?UTF-8?q?=ED=8C=90=20page=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/app.routing.ts | 7 + .../apps/member/partner-office/api.ts | 223 +++++++++++ .../apps/member/partner-office/data.ts | 33 ++ src/app/mock-api/common/navigation/data.ts | 7 + src/app/mock-api/index.ts | 2 + .../member/partner-office/components/index.ts | 3 + .../components/list.component.html | 363 ++++++++++++++++++ .../components/list.component.ts | 198 ++++++++++ .../models/partner-office-pagination.ts | 8 + .../partner-office/models/partner-office.ts | 29 ++ .../partner-office/partner-office.module.ts | 50 +++ .../partner-office/partner-office.routing.ts | 24 ++ .../resolvers/partner-office.resolver.ts | 89 +++++ .../services/partner-office.service.ts | 161 ++++++++ src/assets/i18n/en.json | 2 +- src/assets/i18n/ko.json | 1 + 16 files changed, 1199 insertions(+), 1 deletion(-) create mode 100644 src/app/mock-api/apps/member/partner-office/api.ts create mode 100644 src/app/mock-api/apps/member/partner-office/data.ts create mode 100644 src/app/modules/admin/member/partner-office/components/index.ts create mode 100644 src/app/modules/admin/member/partner-office/components/list.component.html create mode 100644 src/app/modules/admin/member/partner-office/components/list.component.ts create mode 100644 src/app/modules/admin/member/partner-office/models/partner-office-pagination.ts create mode 100644 src/app/modules/admin/member/partner-office/models/partner-office.ts create mode 100644 src/app/modules/admin/member/partner-office/partner-office.module.ts create mode 100644 src/app/modules/admin/member/partner-office/partner-office.routing.ts create mode 100644 src/app/modules/admin/member/partner-office/resolvers/partner-office.resolver.ts create mode 100644 src/app/modules/admin/member/partner-office/services/partner-office.service.ts diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts index 6c05664..9e0c0c7 100644 --- a/src/app/app.routing.ts +++ b/src/app/app.routing.ts @@ -199,6 +199,13 @@ export const appRoutes: Route[] = [ 'app/modules/admin/member/partner-division/partner-division.module' ).then((m: any) => m.PartnerDivisionModule), }, + { + path: 'partner-office', + loadChildren: () => + import( + 'app/modules/admin/member/partner-office/partner-office.module' + ).then((m: any) => m.PartnerOfficeModule), + }, ], }, { diff --git a/src/app/mock-api/apps/member/partner-office/api.ts b/src/app/mock-api/apps/member/partner-office/api.ts new file mode 100644 index 0000000..8970aa0 --- /dev/null +++ b/src/app/mock-api/apps/member/partner-office/api.ts @@ -0,0 +1,223 @@ +import { Injectable } from '@angular/core'; +import { assign, cloneDeep } from 'lodash-es'; +import { FuseMockApiService, FuseMockApiUtils } from '@fuse/lib/mock-api'; +import { partnerOffices as partnerOfficesData } from './data'; + +@Injectable({ + providedIn: 'root', +}) +export class MemberPartnerOfficeMockApi { + private _partnerOffices: any[] = partnerOfficesData; + + /** + * Constructor + */ + constructor(private _fuseMockApiService: FuseMockApiService) { + // Register Mock API handlers + this.registerHandlers(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Register Mock API handlers + */ + registerHandlers(): void { + // ----------------------------------------------------------------------------------------------------- + // @ PartnerOffices - GET + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onGet('api/apps/member/partner-office/partner-offices', 300) + .reply(({ request }) => { + // Get available queries + const search = request.params.get('search'); + const sort = request.params.get('sort') || 'name'; + const order = request.params.get('order') || 'asc'; + const page = parseInt(request.params.get('page') ?? '1', 10); + const size = parseInt(request.params.get('size') ?? '10', 10); + + // Clone the partnerOffices + let partnerOffices: any[] | null = cloneDeep(this._partnerOffices); + + // Sort the partnerOffices + if (sort === 'sku' || sort === 'name' || sort === 'active') { + partnerOffices.sort((a, b) => { + const fieldA = a[sort].toString().toUpperCase(); + const fieldB = b[sort].toString().toUpperCase(); + return order === 'asc' + ? fieldA.localeCompare(fieldB) + : fieldB.localeCompare(fieldA); + }); + } else { + partnerOffices.sort((a, b) => + order === 'asc' ? a[sort] - b[sort] : b[sort] - a[sort] + ); + } + + // If search exists... + if (search) { + // Filter the partnerOffices + partnerOffices = partnerOffices.filter( + (contact: any) => + contact.name && + contact.name.toLowerCase().includes(search.toLowerCase()) + ); + } + + // Paginate - Start + const partnerOfficesLength = partnerOffices.length; + + // Calculate pagination details + const begin = page * size; + const end = Math.min(size * (page + 1), partnerOfficesLength); + const lastPage = Math.max(Math.ceil(partnerOfficesLength / size), 1); + + // Prepare the pagination object + let pagination = {}; + + // If the requested page number is bigger than + // the last possible page number, return null for + // partnerOffices but also send the last possible page so + // the app can navigate to there + if (page > lastPage) { + partnerOffices = null; + pagination = { + lastPage, + }; + } else { + // Paginate the results by size + partnerOffices = partnerOffices.slice(begin, end); + + // Prepare the pagination mock-api + pagination = { + length: partnerOfficesLength, + size: size, + page: page, + lastPage: lastPage, + startIndex: begin, + endIndex: end - 1, + }; + } + + // Return the response + return [ + 200, + { + partnerOffices, + pagination, + }, + ]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerOffice - GET + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onGet('api/apps/member/partne-office/partner-office') + .reply(({ request }) => { + // Get the id from the params + const id = request.params.get('id'); + + // Clone the partnerOffices + const partnerOffices = cloneDeep(this._partnerOffices); + + // Find the partnerOffice + const partnerOffice = partnerOffices.find( + (item: any) => item.id === id + ); + + // Return the response + return [200, partnerOffice]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerOffice - POST + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onPost('api/apps/member/partner-office/partner-office') + .reply(() => { + // Generate a new partnerOffice + const newPartnerOffice = { + id: FuseMockApiUtils.guid(), + category: '', + name: 'A New User', + description: '', + tags: [], + sku: '', + barcode: '', + brand: '', + vendor: '', + stock: '', + reserved: '', + cost: '', + basePrice: '', + taxPercent: '', + price: '', + weight: '', + thumbnail: '', + images: [], + active: false, + }; + + // Unshift the new partnerOffice + this._partnerOffices.unshift(newPartnerOffice); + + // Return the response + return [200, newPartnerOffice]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerOffice - PATCH + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onPatch('api/apps/member/partner-office/partner-office') + .reply(({ request }) => { + // Get the id and partnerOffice + const id = request.body.id; + const partnerOffice = cloneDeep(request.body.partnerOffice); + + // Prepare the updated partnerOffice + let updatedPartnerOffice = null; + + // Find the partnerOffice and update it + this._partnerOffices.forEach((item, index, partnerOffices) => { + if (item.id === id) { + // Update the partnerOffice + partnerOffices[index] = assign( + {}, + partnerOffices[index], + partnerOffice + ); + + // Store the updated partnerOffice + updatedPartnerOffice = partnerOffices[index]; + } + }); + + // Return the response + return [200, updatedPartnerOffice]; + }); + + // ----------------------------------------------------------------------------------------------------- + // @ PartnerOffice - DELETE + // ----------------------------------------------------------------------------------------------------- + this._fuseMockApiService + .onDelete('api/apps/member/partner-office/partner-office') + .reply(({ request }) => { + // Get the id + const id = request.params.get('id'); + + // Find the partnerOffice and delete it + this._partnerOffices.forEach((item, index) => { + if (item.id === id) { + this._partnerOffices.splice(index, 1); + } + }); + + // Return the response + return [200, true]; + }); + } +} diff --git a/src/app/mock-api/apps/member/partner-office/data.ts b/src/app/mock-api/apps/member/partner-office/data.ts new file mode 100644 index 0000000..aad813a --- /dev/null +++ b/src/app/mock-api/apps/member/partner-office/data.ts @@ -0,0 +1,33 @@ +/* eslint-disable */ + +export const partnerOffices = [ + { + id: 'on00', + totalPartnerCount: '5', + totalHoldingMoney: 303675, + totalComp: 108933, + total: 412608, + branchCount: 1, + divisionCount: 1, + officeCount: 1, + storeCount: 1, + memberCount: 1, + nickname: 'on00', + accountHolder: '11', + phoneNumber: '010-1111-1111', + calculateType: '롤링', + ownCash: 50000, + ownComp: 1711, + ownCoupon: 50000, + gameMoney: 0, + todayComp: 0, + totalDeposit: 0, + totalWithdraw: 0, + balance: 0, + registDate: '2022-06-12 15:38', + finalSigninDate: '', + ip: '', + state: '정상', + note: '매장등록', + }, +]; diff --git a/src/app/mock-api/common/navigation/data.ts b/src/app/mock-api/common/navigation/data.ts index 51055d0..d7bbdce 100644 --- a/src/app/mock-api/common/navigation/data.ts +++ b/src/app/mock-api/common/navigation/data.ts @@ -95,6 +95,13 @@ export const defaultNavigation: FuseNavigationItem[] = [ icon: 'heroicons_outline:academic-cap', link: '/member/partner-division', }, + { + id: 'member.partner-office', + title: 'Partner Office', + type: 'basic', + icon: 'heroicons_outline:academic-cap', + link: '/member/partner-office', + }, ], }, { diff --git a/src/app/mock-api/index.ts b/src/app/mock-api/index.ts index 45a883c..4449d8e 100644 --- a/src/app/mock-api/index.ts +++ b/src/app/mock-api/index.ts @@ -18,6 +18,7 @@ import { MemberCurrentUserMockApi } from './apps/member/current-user/api'; import { MemberPartnerMockApi } from './apps/member/partner/api'; import { MemberPartnerBranchMockApi } from './apps/member/partner-branch/api'; import { MemberPartnerDivisionMockApi } from './apps/member/partner-division/api'; +import { MemberPartnerOfficeMockApi } from './apps/member/partner-office/api'; import { MessagesMockApi } from 'app/mock-api/common/messages/api'; import { NavigationMockApi } from 'app/mock-api/common/navigation/api'; import { NotesMockApi } from 'app/mock-api/apps/notes/api'; @@ -56,6 +57,7 @@ export const mockApiServices = [ MemberPartnerMockApi, MemberPartnerBranchMockApi, MemberPartnerDivisionMockApi, + MemberPartnerOfficeMockApi, MessagesMockApi, NavigationMockApi, NotesMockApi, diff --git a/src/app/modules/admin/member/partner-office/components/index.ts b/src/app/modules/admin/member/partner-office/components/index.ts new file mode 100644 index 0000000..04759eb --- /dev/null +++ b/src/app/modules/admin/member/partner-office/components/index.ts @@ -0,0 +1,3 @@ +import { ListComponent } from './list.component'; + +export const COMPONENTS = [ListComponent]; diff --git a/src/app/modules/admin/member/partner-office/components/list.component.html b/src/app/modules/admin/member/partner-office/components/list.component.html new file mode 100644 index 0000000..a3a604e --- /dev/null +++ b/src/app/modules/admin/member/partner-office/components/list.component.html @@ -0,0 +1,363 @@ +
+ +
+ +
+ +
+ +
총판
+ +
+ + + + + + + 40 + 60 + 80 + 100 + + + + + LV.1 + LV.2 + LV.3 + LV.4 + + + + + 정상 + 대기 + 탈퇴 + 휴면 + 블랙 + 정지 + + + + + 카지노제한 + 슬롯제한 + + + + + 계좌입금 + + + + + 카지노콤프 + 슬롯콤프 + 배팅콤프 + 첫충콤프 + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + +
+
+ + +
+ There are no partner offices! +
+
+
+
+
diff --git a/src/app/modules/admin/member/partner-office/components/list.component.ts b/src/app/modules/admin/member/partner-office/components/list.component.ts new file mode 100644 index 0000000..1b195ba --- /dev/null +++ b/src/app/modules/admin/member/partner-office/components/list.component.ts @@ -0,0 +1,198 @@ +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + OnDestroy, + OnInit, + ViewChild, + ViewEncapsulation, +} from '@angular/core'; +import { + FormBuilder, + FormControl, + FormGroup, + Validators, +} from '@angular/forms'; +import { MatCheckboxChange } from '@angular/material/checkbox'; +import { MatPaginator } from '@angular/material/paginator'; +import { MatSort } from '@angular/material/sort'; +import { + debounceTime, + map, + merge, + Observable, + Subject, + switchMap, + takeUntil, +} from 'rxjs'; +import { fuseAnimations } from '@fuse/animations'; +import { FuseConfirmationService } from '@fuse/services/confirmation'; + +import { User } from '../../user/models/user'; +import { PartnerOffice } from '../models/partner-office'; +import { PartnerOfficePagination } from '../models/partner-office-pagination'; +import { PartnerOfficeService } from '../services/partner-office.service'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'partner-office-list', + templateUrl: './list.component.html', + styles: [ + /* language=SCSS */ + ` + .inventory-grid { + grid-template-columns: 60px auto 40px; + + @screen sm { + grid-template-columns: 60px 60px 60px 60px 60px 60px auto 60px; + } + + @screen md { + grid-template-columns: 60px 60px 60px 60px 60px 60px auto 60px 60px; + } + + @screen lg { + grid-template-columns: 60px 70px 70px 70px 70px 100px 60px 60px auto 60px 60px 60px 60px; + } + } + `, + ], + encapsulation: ViewEncapsulation.None, + changeDetection: ChangeDetectionStrategy.OnPush, + animations: fuseAnimations, +}) +export class ListComponent implements OnInit, AfterViewInit, OnDestroy { + @ViewChild(MatPaginator) private _paginator!: MatPaginator; + @ViewChild(MatSort) private _sort!: MatSort; + + partnerOffices$!: Observable; + users$!: Observable; + + isLoading = false; + searchInputControl = new FormControl(); + selectedPartnerOffice?: PartnerOffice; + pagination?: PartnerOfficePagination; + + private _unsubscribeAll: Subject = new Subject(); + + /** + * Constructor + */ + constructor( + private _changeDetectorRef: ChangeDetectorRef, + private _fuseConfirmationService: FuseConfirmationService, + private _formBuilder: FormBuilder, + private _partnerOfficeService: PartnerOfficeService, + private router: Router + ) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Lifecycle hooks + // ----------------------------------------------------------------------------------------------------- + + /** + * On init + */ + ngOnInit(): void { + // Get the pagination + this._partnerOfficeService.pagination$ + .pipe(takeUntil(this._unsubscribeAll)) + .subscribe((pagination: PartnerOfficePagination | undefined) => { + // Update the pagination + this.pagination = pagination; + + // Mark for check + this._changeDetectorRef.markForCheck(); + }); + + // Get the products + this.partnerOffices$ = this._partnerOfficeService.partnerOffices$; + } + + /** + * After view init + */ + ngAfterViewInit(): void { + if (this._sort && this._paginator) { + // Set the initial sort + this._sort.sort({ + id: 'name', + start: 'asc', + disableClear: true, + }); + + // Mark for check + this._changeDetectorRef.markForCheck(); + + // If the partnerOffice changes the sort order... + this._sort.sortChange + .pipe(takeUntil(this._unsubscribeAll)) + .subscribe(() => { + // Reset back to the first page + this._paginator.pageIndex = 0; + }); + + // Get products if sort or page changes + merge(this._sort.sortChange, this._paginator.page) + .pipe( + switchMap(() => { + this.isLoading = true; + return this._partnerOfficeService.getPartnerOffices( + this._paginator.pageIndex, + this._paginator.pageSize, + this._sort.active, + this._sort.direction + ); + }), + map(() => { + this.isLoading = false; + }) + ) + .subscribe(); + } + } + + /** + * On destroy + */ + ngOnDestroy(): void { + // Unsubscribe from all subscriptions + this._unsubscribeAll.next(null); + this._unsubscribeAll.complete(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + viewUserDetail(id: string): void { + let url: string = 'member/user/' + id; + this.router.navigateByUrl(url); + } + // ----------------------------------------------------------------------------------------------------- + // @ Private methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Create product + */ + __createProduct(): void {} + + /** + * Toggle product details + * + * @param productId + */ + __toggleDetails(productId: string): void {} + + /** + * Track by function for ngFor loops + * + * @param index + * @param item + */ + __trackByFn(index: number, item: any): any { + return item.id || index; + } +} diff --git a/src/app/modules/admin/member/partner-office/models/partner-office-pagination.ts b/src/app/modules/admin/member/partner-office/models/partner-office-pagination.ts new file mode 100644 index 0000000..02b7f59 --- /dev/null +++ b/src/app/modules/admin/member/partner-office/models/partner-office-pagination.ts @@ -0,0 +1,8 @@ +export interface PartnerOfficePagination { + length: number; + size: number; + page: number; + lastPage: number; + startIndex: number; + endIndex: number; +} diff --git a/src/app/modules/admin/member/partner-office/models/partner-office.ts b/src/app/modules/admin/member/partner-office/models/partner-office.ts new file mode 100644 index 0000000..8d614ca --- /dev/null +++ b/src/app/modules/admin/member/partner-office/models/partner-office.ts @@ -0,0 +1,29 @@ +export interface PartnerOffice { + id?: string; + totalPartnerCount?: number; + totalHoldingMoney?: number; + totalComp?: number; + total?: number; + branchCount?: number; + divisionCount?: number; + officeCount?: number; + storeCount?: number; + memberCount?: number; + nickname?: string; + accountHolder?: string; + phoneNumber?: string; + calculateType?: string; + ownCash?: number; + ownComp?: number; + ownCoupon?: number; + gameMoney?: number; + todayComp?: number; + totalDeposit?: number; + totalWithdraw?: number; + balance?: number; + registDate?: string; + finalSigninDate?: string; + ip?: string; + state?: string; + note?: string; +} diff --git a/src/app/modules/admin/member/partner-office/partner-office.module.ts b/src/app/modules/admin/member/partner-office/partner-office.module.ts new file mode 100644 index 0000000..6e29f32 --- /dev/null +++ b/src/app/modules/admin/member/partner-office/partner-office.module.ts @@ -0,0 +1,50 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { MatButtonModule } from '@angular/material/button'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatPaginatorModule } from '@angular/material/paginator'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { MatRippleModule } from '@angular/material/core'; +import { MatSortModule } from '@angular/material/sort'; +import { MatSelectModule } from '@angular/material/select'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { MatGridListModule } from '@angular/material/grid-list'; +import { MatSlideToggleModule } from '@angular/material/slide-toggle'; +import { MatRadioModule } from '@angular/material/radio'; +import { MatCheckboxModule } from '@angular/material/checkbox'; + +import { TranslocoModule } from '@ngneat/transloco'; + +import { SharedModule } from 'app/shared/shared.module'; + +import { COMPONENTS } from './components'; + +import { partnerOfficeRoutes } from './partner-office.routing'; + +@NgModule({ + declarations: [COMPONENTS], + imports: [ + TranslocoModule, + SharedModule, + RouterModule.forChild(partnerOfficeRoutes), + + MatButtonModule, + MatFormFieldModule, + MatIconModule, + MatInputModule, + MatPaginatorModule, + MatProgressBarModule, + MatRippleModule, + MatSortModule, + MatSelectModule, + MatTooltipModule, + MatGridListModule, + MatSlideToggleModule, + MatRadioModule, + MatCheckboxModule, + ], +}) +export class PartnerOfficeModule {} diff --git a/src/app/modules/admin/member/partner-office/partner-office.routing.ts b/src/app/modules/admin/member/partner-office/partner-office.routing.ts new file mode 100644 index 0000000..698070b --- /dev/null +++ b/src/app/modules/admin/member/partner-office/partner-office.routing.ts @@ -0,0 +1,24 @@ +import { Route } from '@angular/router'; + +import { ListComponent } from './components/list.component'; +import { ViewComponent } from '../user/components/view.component'; + +import { PartnerOfficesResolver } from './resolvers/partner-office.resolver'; +import { UserResolver } from '../user/resolvers/user.resolver'; + +export const partnerOfficeRoutes: Route[] = [ + { + path: '', + component: ListComponent, + resolve: { + partnerOffices: PartnerOfficesResolver, + }, + }, + { + path: ':id', + component: ViewComponent, + resolve: { + users: UserResolver, + }, + }, +]; diff --git a/src/app/modules/admin/member/partner-office/resolvers/partner-office.resolver.ts b/src/app/modules/admin/member/partner-office/resolvers/partner-office.resolver.ts new file mode 100644 index 0000000..ab2b3b9 --- /dev/null +++ b/src/app/modules/admin/member/partner-office/resolvers/partner-office.resolver.ts @@ -0,0 +1,89 @@ +import { Injectable } from '@angular/core'; +import { + ActivatedRouteSnapshot, + Resolve, + Router, + RouterStateSnapshot, +} from '@angular/router'; +import { catchError, Observable, throwError } from 'rxjs'; + +import { PartnerOffice } from '../models/partner-office'; +import { PartnerOfficePagination } from '../models/partner-office-pagination'; +import { PartnerOfficeService } from '../services/partner-office.service'; + +@Injectable({ + providedIn: 'root', +}) +export class PartnerOfficeResolver implements Resolve { + /** + * Constructor + */ + constructor( + private _partnerOfficeService: PartnerOfficeService, + private _router: Router + ) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Resolver + * + * @param route + * @param state + */ + resolve( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable { + return this._partnerOfficeService + .getPartnerOfficeById(route.paramMap.get('id')) + .pipe( + // Error here means the requested product is not available + catchError((error) => { + // Log the error + console.error(error); + + // Get the parent url + const parentUrl = state.url.split('/').slice(0, -1).join('/'); + + // Navigate to there + this._router.navigateByUrl(parentUrl); + + // Throw an error + return throwError(error); + }) + ); + } +} + +@Injectable({ + providedIn: 'root', +}) +export class PartnerOfficesResolver implements Resolve { + /** + * Constructor + */ + constructor(private _partnerOfficeService: PartnerOfficeService) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Resolver + * + * @param route + * @param state + */ + resolve( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot + ): Observable<{ + pagination: PartnerOfficePagination; + partnerOffices: PartnerOffice[]; + }> { + return this._partnerOfficeService.getPartnerOffices(); + } +} diff --git a/src/app/modules/admin/member/partner-office/services/partner-office.service.ts b/src/app/modules/admin/member/partner-office/services/partner-office.service.ts new file mode 100644 index 0000000..0bb8943 --- /dev/null +++ b/src/app/modules/admin/member/partner-office/services/partner-office.service.ts @@ -0,0 +1,161 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { + BehaviorSubject, + filter, + map, + Observable, + of, + switchMap, + take, + tap, + throwError, +} from 'rxjs'; + +import { PartnerOffice } from '../models/partner-office'; +import { PartnerOfficePagination } from '../models/partner-office-pagination'; + +@Injectable({ + providedIn: 'root', +}) +export class PartnerOfficeService { + // Private + private __pagination = new BehaviorSubject< + PartnerOfficePagination | undefined + >(undefined); + private __partnerOffice = new BehaviorSubject( + undefined + ); + private __partnerOffices = new BehaviorSubject( + undefined + ); + + /** + * Constructor + */ + constructor(private _httpClient: HttpClient) {} + + // ----------------------------------------------------------------------------------------------------- + // @ Accessors + // ----------------------------------------------------------------------------------------------------- + + /** + * Getter for pagination + */ + get pagination$(): Observable { + return this.__pagination.asObservable(); + } + + /** + * Getter for partnerOffice + */ + get partnerOffice$(): Observable { + return this.__partnerOffice.asObservable(); + } + + /** + * Getter for partnerOffices + */ + get partnerOffices$(): Observable { + return this.__partnerOffices.asObservable(); + } + + // ----------------------------------------------------------------------------------------------------- + // @ Public methods + // ----------------------------------------------------------------------------------------------------- + + /** + * Get partnerOffices + * + * + * @param page + * @param size + * @param sort + * @param order + * @param search + */ + getPartnerOffices( + page: number = 0, + size: number = 10, + sort: string = 'name', + order: 'asc' | 'desc' | '' = 'asc', + search: string = '' + ): Observable<{ + pagination: PartnerOfficePagination; + partnerOffices: PartnerOffice[]; + }> { + return this._httpClient + .get<{ + pagination: PartnerOfficePagination; + partnerOffices: PartnerOffice[]; + }>('api/apps/member/partner-office/partner-offices', { + params: { + page: '' + page, + size: '' + size, + sort, + order, + search, + }, + }) + .pipe( + tap((response) => { + this.__pagination.next(response.pagination); + this.__partnerOffices.next(response.partnerOffices); + }) + ); + } + + /** + * Get product by id + */ + getPartnerOfficeById(id: string | null): Observable { + return this.__partnerOffices.pipe( + take(1), + map((partnerOffices) => { + // Find the product + const partnerOffice = + partnerOffices?.find((item) => item.id === id) || undefined; + + // Update the product + this.__partnerOffice.next(partnerOffice); + + // Return the product + return partnerOffice; + }), + switchMap((product) => { + if (!product) { + return throwError('Could not found product with id of ' + id + '!'); + } + + return of(product); + }) + ); + } + + /** + * Create product + */ + createPartnerOffice(): Observable { + return this.partnerOffices$.pipe( + take(1), + switchMap((partnerOffices) => + this._httpClient + .post('api/apps/member/partner-office/product', {}) + .pipe( + map((newPartnerOffice) => { + // Update the partnerOffices with the new product + if (!!partnerOffices) { + this.__partnerOffices.next([ + newPartnerOffice, + ...partnerOffices, + ]); + } + + // Return the new product + return newPartnerOffice; + }) + ) + ) + ); + } +} diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index a4a3279..2c877da 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -10,7 +10,7 @@ "Partner Mainoffice": "Partner Mainoffice", "Partner Branch": "Partner Branch", "Partner Division": "Partner Division", - "Mainoffice": "Mainoffice", + "Partner Office": "Partner Office", "Analytics": "Analytics", "Deposit": "Deposit", "Withdraw": "Withdraw", diff --git a/src/assets/i18n/ko.json b/src/assets/i18n/ko.json index f67e407..31ece60 100644 --- a/src/assets/i18n/ko.json +++ b/src/assets/i18n/ko.json @@ -10,6 +10,7 @@ "Partner Mainoffice": "본사", "Partner Branch": "대본", "Partner Division": "부본", + "Partner Office": "총판", "Analytics": "Analytics", "Deposit": "입금관리", "Withdraw": "출금관리",