Сделал фильтрацию по дате, локализовал календарь на русский язык и формат
This commit is contained in:
gofnnp 2023-03-30 11:13:35 +04:00
parent 1a503b3163
commit 7f96fa4503
11 changed files with 408 additions and 106 deletions

View File

@ -1,109 +1,144 @@
import {MainPageCode, OrderStatus, Page, PageCode, PaymentMethod} from "./interface/data"; import { MatDateFormats } from '@angular/material/core';
import {
IOptionDateFilter,
MainPageCode,
OrderStatus,
Page,
PageCode,
PaymentMethod,
} from './interface/data';
export const PageList: Page[] = [ export const PageList: Page[] = [
// { // {
// code: PageCode.Auth, // code: PageCode.Auth,
// name: 'Вход', // name: 'Вход',
// resName: 'auth', // resName: 'auth',
// onSideBar: false, // onSideBar: false,
// }, // },
{ {
code: PageCode.Orders, code: PageCode.Orders,
name: 'Заказы', name: 'Заказы',
resName: 'orders', resName: 'orders',
onSideBar: true, onSideBar: true,
}, },
]; ];
export const PageListWithBonus: Page[] = [ export const PageListWithBonus: Page[] = [
// { // {
// code: PageCode.Auth, // code: PageCode.Auth,
// name: 'Вход', // name: 'Вход',
// resName: 'auth', // resName: 'auth',
// onSideBar: false, // onSideBar: false,
// }, // },
{ {
code: PageCode.BonusProgram, code: PageCode.BonusProgram,
name: 'Ваша карта лояльности', name: 'Ваша карта лояльности',
description: '', description: '',
resName: 'bonus-program', resName: 'bonus-program',
onSideBar: false, onSideBar: false,
}, },
{ {
code: PageCode.Orders, code: PageCode.Orders,
name: 'Ваши чеки', name: 'Ваши чеки',
description: '', description: '',
resName: 'orders', resName: 'orders',
onSideBar: true, onSideBar: true,
}, },
// { // {
// code: PageCode.UserData, // code: PageCode.UserData,
// name: 'Заполнить анкету', // name: 'Заполнить анкету',
// description: '', // description: '',
// resName: 'user-data', // resName: 'user-data',
// onSideBar: true // onSideBar: true
// }, // },
// { // {
// code: PageCode.RefSystem, // code: PageCode.RefSystem,
// name: 'Пригласить друга', // name: 'Пригласить друга',
// description: '', // description: '',
// resName: 'ref-system', // resName: 'ref-system',
// onSideBar: true, // onSideBar: true,
// }, // },
]; ];
export const PageListMain: Page[] = [ export const PageListMain: Page[] = [
{ {
code: MainPageCode.Account, code: MainPageCode.Account,
name: 'Аккаунт', name: 'Аккаунт',
resName: 'account', resName: 'account',
onSideBar: true, onSideBar: true,
icon: 'person' icon: 'person',
}, },
{ {
code: MainPageCode.Products, code: MainPageCode.Products,
name: 'Товары', name: 'Товары',
resName: 'products', resName: 'products',
onSideBar: true, onSideBar: true,
icon: 'manage_search' icon: 'manage_search',
}, },
{ {
code: MainPageCode.Cart, code: MainPageCode.Cart,
name: 'Корзина', name: 'Корзина',
resName: 'cart', resName: 'cart',
onSideBar: true, onSideBar: true,
icon: 'shopping_bag' icon: 'shopping_bag',
}, },
// { // {
// code: MainPageCode.Info, // code: MainPageCode.Info,
// name: 'О нас', // name: 'О нас',
// resName: 'info', // resName: 'info',
// onSideBar: true, // onSideBar: true,
// icon: 'info' // icon: 'info'
// }, // },
] ];
export const orderStatuses: OrderStatus = { export const orderStatuses: OrderStatus = {
'Cancelled': 'Отменен', Cancelled: 'Отменен',
'InProcessing': 'В обработке', InProcessing: 'В обработке',
'Unconfirmed': 'Принят', Unconfirmed: 'Принят',
'WaitCooking': 'Принят', WaitCooking: 'Принят',
'ReadyForCooking': 'Принят', ReadyForCooking: 'Принят',
'CookingStarted': 'Готовится', CookingStarted: 'Готовится',
'CookingCompleted': 'Приготовлен', CookingCompleted: 'Приготовлен',
'Waiting': 'В пути', Waiting: 'В пути',
'OnWay': 'В пути', OnWay: 'В пути',
'Delivered': 'Выполнен', Delivered: 'Выполнен',
'Closed': 'Выполнен', Closed: 'Выполнен',
}; };
export const paymentMethods: PaymentMethod[] = [ export const paymentMethods: PaymentMethod[] = [
{ {
type: 'Card', type: 'Card',
label: 'Безналичный расчет' label: 'Безналичный расчет',
}, },
{ {
type: 'Cash', type: 'Cash',
label: 'Наличными' label: 'Наличными',
} },
] ];
export const dateFilterOptions: IOptionDateFilter[] = [
{
name: 'Текущий месяц',
value: 'currentMonth',
},
{
name: 'Прошлый месяц',
value: 'lastMonth',
},
{
name: 'Между',
value: 'between',
},
];
export const APP_DATE_FORMATS: MatDateFormats = {
parse: {
dateInput: { month: 'short', year: 'numeric', day: 'numeric' },
},
display: {
dateInput: 'input',
monthYearLabel: { year: 'numeric', month: 'numeric' },
dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },
monthYearA11yLabel: { year: 'numeric', month: 'long' },
},
};

View File

@ -74,6 +74,9 @@ import { MatSnackBarModule } from '@angular/material/snack-bar';
import { SnackBarComponent } from './components/snack-bar/snack-bar.component'; import { SnackBarComponent } from './components/snack-bar/snack-bar.component';
import {MatDialogModule} from '@angular/material/dialog'; import {MatDialogModule} from '@angular/material/dialog';
import { PurchaseInfoComponent } from './components/purchase-info/purchase-info.component'; import { PurchaseInfoComponent } from './components/purchase-info/purchase-info.component';
import { DateFilterComponent } from './components/date-filter/date-filter.component';
import {MatDatepickerModule} from '@angular/material/datepicker';
import {MatNativeDateModule} from '@angular/material/core';
const routes: Routes = [ const routes: Routes = [
{ path: '', redirectTo: 'products', pathMatch: 'full' }, { path: '', redirectTo: 'products', pathMatch: 'full' },
@ -113,6 +116,7 @@ const routes: Routes = [
TerminalListComponent, TerminalListComponent,
SnackBarComponent, SnackBarComponent,
PurchaseInfoComponent, PurchaseInfoComponent,
DateFilterComponent,
], ],
imports: [ imports: [
BrowserModule, BrowserModule,
@ -162,7 +166,9 @@ const routes: Routes = [
MatButtonModule, MatButtonModule,
MatListModule, MatListModule,
MatSnackBarModule, MatSnackBarModule,
MatDialogModule MatDialogModule,
MatDatepickerModule,
MatNativeDateModule
], ],
providers: [ providers: [
DialogService, DialogService,

View File

@ -0,0 +1,43 @@
<div class="date-filter-container">
<form [formGroup]="dateFilterForm" (ngSubmit)="submitFilter()">
<mat-form-field appearance="fill">
<mat-select formControlName="filterType">
<mat-option *ngFor="let option of options" [value]="option.value">{{
option.name
}}</mat-option>
</mat-select>
<mat-label>Фильтр</mat-label>
<mat-hint>Тип</mat-hint>
</mat-form-field>
<div
*ngIf="currentFilterType === 'between'"
class="date-filter-container__date-inputs"
>
<mat-form-field class="date-range-input-field" appearance="fill">
<mat-label>Интервал времени</mat-label>
<mat-date-range-input
[rangePicker]="campaignTwoPicker"
[comparisonStart]="dateFilterForm.value.from"
[comparisonEnd]="dateFilterForm.value.to"
>
<input matStartDate placeholder="От: " formControlName="from" />
<input matEndDate placeholder="До: " formControlName="to" />
</mat-date-range-input>
<mat-hint>дд.мм.гггг дд.мм.гггг</mat-hint>
<mat-datepicker-toggle
matIconSuffix
[for]="campaignTwoPicker"
></mat-datepicker-toggle>
<mat-date-range-picker #campaignTwoPicker>
<mat-date-range-picker-actions>
<button mat-button matDateRangePickerCancel>Назад</button>
<button mat-raised-button color="primary" matDateRangePickerApply>
Подтвердить
</button>
</mat-date-range-picker-actions>
</mat-date-range-picker>
</mat-form-field>
</div>
<button mat-stroked-button class="apply" type="submit">Применить</button>
</form>
</div>

View File

@ -0,0 +1,28 @@
:host {
.date-filter-container {
& > form {
width: 100%;
display: flex;
flex-direction: row;
gap: 8px;
}
}
}
@media screen and (max-width: 1065px) {
:host {
.date-filter-container {
& > form {
flex-direction: column;
}
}
}
.date-range-input-field {
width: 100%;
}
}
.apply {
height: 51.67px;
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DateFilterComponent } from './date-filter.component';
describe('DateFilterComponent', () => {
let component: DateFilterComponent;
let fixture: ComponentFixture<DateFilterComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ DateFilterComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(DateFilterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,70 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import moment from 'moment';
import { APP_DATE_FORMATS } from 'src/app/app.constants';
import { IDateFilter, IOptionDateFilter } from 'src/app/interface/data';
import { DateAdapterService } from 'src/app/services/date-adapter.service';
@Component({
selector: 'app-date-filter[options]',
templateUrl: './date-filter.component.html',
styleUrls: ['./date-filter.component.scss'],
providers: [
{ provide: DateAdapter, useClass: DateAdapterService },
{ provide: MAT_DATE_FORMATS, useValue: APP_DATE_FORMATS },
{ provide: MAT_DATE_LOCALE, useValue: 'ru-RU' }
],
})
export class DateFilterComponent implements OnInit {
@Input() defaultFilterType!: string;
@Output() onSubmitFilter = new EventEmitter<any>();
@Input() options!: IOptionDateFilter[];
public currentFilterType!: string;
public dateFilterForm = new FormGroup({
filterType: new FormControl<string>(''),
from: new FormControl<Date | null>(null),
to: new FormControl<Date | null>(null),
});
constructor(private _snackBar: MatSnackBar) {}
ngOnInit(): void {
this.currentFilterType = this.defaultFilterType
? this.defaultFilterType
: this.options[0].value;
const filterType = this.dateFilterForm.get('filterType');
filterType?.setValue(this.currentFilterType);
filterType?.valueChanges.subscribe({
next: (value) => {
this.currentFilterType = value ?? '';
const fromControl = this.dateFilterForm.get('from')
const toControl = this.dateFilterForm.get('to')
if (this.currentFilterType === 'between') {
this.dateFilterForm.controls.from.addValidators([
Validators.required,
]);
this.dateFilterForm.controls.to.addValidators([Validators.required]);
} else {
fromControl?.clearValidators()
toControl?.clearValidators()
}
fromControl?.updateValueAndValidity()
toControl?.updateValueAndValidity()
},
});
}
submitFilter() {
if (!this.dateFilterForm.valid) {
this._snackBar.open('Заполните все поля!', 'Ок', {
duration: 2000,
});
}
this.onSubmitFilter.emit(this.dateFilterForm.value)
}
}

View File

@ -275,3 +275,14 @@ export interface ITerminal {
label: string; label: string;
id: string; id: string;
} }
export interface IOptionDateFilter {
name: string;
value: string;
}
export interface IDateFilter {
filterType: string;
from?: Date;
to?: Date;
}

View File

@ -1,3 +1,9 @@
<app-date-filter
[options]="dateFilterOptions"
[defaultFilterType]="defaultFilterType"
(onSubmitFilter)="dateFilter($event)"
></app-date-filter>
<div class="orders"> <div class="orders">
<!-- <h2>{{ currentPage.name }}</h2> --> <!-- <h2>{{ currentPage.name }}</h2> -->
<table <table
@ -63,14 +69,25 @@
class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-bonuses" class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-bonuses"
data-title="Бонусы" data-title="Бонусы"
[ngClass]="{ [ngClass]="{
'red-color': purchase.transactionSum ? purchase.transactionSum < 0 : false, 'red-color': purchase.transactionSum
'green-color': purchase.transactionSum ? purchase.transactionSum > 0 : false ? purchase.transactionSum < 0
: false,
'green-color': purchase.transactionSum
? purchase.transactionSum > 0
: false
}" }"
> >
{{ purchase.transactionSum }} {{ purchase.transactionSum }}
</td> </td>
<td *ngIf="purchase.more_info" class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-actions" data-title="Действия"> <td
<button mat-stroked-button (click)="showPurchaseInfo(purchase.more_info)" > *ngIf="purchase.more_info"
class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-actions"
data-title="Действия"
>
<button
mat-stroked-button
(click)="showPurchaseInfo(purchase.more_info)"
>
Подробнее Подробнее
</button> </button>
</td> </td>
@ -78,12 +95,15 @@
</tbody> </tbody>
</table> </table>
<p <p
*ngIf="purchases.length !== purchasesShortArray.length" *ngIf="filteredOfDatePurchases.length !== purchasesShortArray.length && purchasesShortArray.length"
class="show-more-orders" class="show-more-orders"
(click)="getMoreOrders()" (click)="getMoreOrders()"
> >
Показать больше Показать больше
</p> </p>
<p *ngIf="!purchasesShortArray.length && !ordersLoadingStatus" class="show-more-orders">
Данные не найдены
</p>
<p-progressSpinner <p-progressSpinner
*ngIf="ordersLoadingStatus" *ngIf="ordersLoadingStatus"
[style]="{ width: '100%' }" [style]="{ width: '100%' }"

View File

@ -1,6 +1,6 @@
import { HttpErrorResponse } from '@angular/common/http'; import { HttpErrorResponse } from '@angular/common/http';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Page, Purchase, PurchaseInfo } from 'src/app/interface/data'; import { IDateFilter, Page, Purchase, PurchaseInfo } from 'src/app/interface/data';
import * as moment from 'moment-timezone'; import * as moment from 'moment-timezone';
import { lastValueFrom } from 'rxjs'; import { lastValueFrom } from 'rxjs';
import { WpJsonService } from 'src/app/services/wp-json.service'; import { WpJsonService } from 'src/app/services/wp-json.service';
@ -8,6 +8,7 @@ import { environment } from 'src/environments/environment';
import { CookiesService } from 'src/app/services/cookies.service'; import { CookiesService } from 'src/app/services/cookies.service';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { PurchaseInfoComponent } from 'src/app/components/purchase-info/purchase-info.component'; import { PurchaseInfoComponent } from 'src/app/components/purchase-info/purchase-info.component';
import { dateFilterOptions } from 'src/app/app.constants';
@Component({ @Component({
selector: 'app-orders', selector: 'app-orders',
@ -24,6 +25,12 @@ export class OrdersComponent implements OnInit {
public purchases: Purchase[] = []; public purchases: Purchase[] = [];
public purchasesShortArray: Purchase[] = []; public purchasesShortArray: Purchase[] = [];
public dateFilterOptions = dateFilterOptions
public defaultFilterType = 'currentMonth';
private startOfMonth = moment().startOf('month').format('YYYY-MM-DD HH:mm');
public filteredOfDatePurchases: Purchase[] = []
constructor( constructor(
private wpJsonService: WpJsonService, private wpJsonService: WpJsonService,
private cookiesService: CookiesService, private cookiesService: CookiesService,
@ -34,6 +41,35 @@ export class OrdersComponent implements OnInit {
this.getOrders(); this.getOrders();
} }
dateFilter(dateFilter: IDateFilter) {
this.lastViewOrder = 3
switch (dateFilter.filterType) {
case 'between':
this.filteredOfDatePurchases = this.purchases.filter((value) => {
return moment(value.transactionCreateDate).isBetween(dateFilter.from, moment(dateFilter.to).add(1, 'day'))
})
break;
case 'currentMonth':
this.filteredOfDatePurchases = this.purchases.filter((value) => {
return moment(value.transactionCreateDate).isAfter(this.startOfMonth)
})
break;
case 'lastMonth':
this.filteredOfDatePurchases = this.purchases.filter((value) => {
return moment(value.transactionCreateDate).isBetween(moment(this.startOfMonth).subtract(1, 'month'), this.startOfMonth)
})
break;
default:
this.filteredOfDatePurchases = this.purchases
break;
}
this.purchasesShortArray = this.filteredOfDatePurchases.slice(0, this.lastViewOrder);
}
async getOrders() { async getOrders() {
const token = this.cookiesService.getItem('token'); const token = this.cookiesService.getItem('token');
if (!token) { if (!token) {
@ -98,13 +134,13 @@ export class OrdersComponent implements OnInit {
) )
); );
this.purchasesShortArray = this.purchases.slice(0, this.lastViewOrder); this.dateFilter({filterType: this.defaultFilterType})
this.ordersLoadingStatus = false; this.ordersLoadingStatus = false;
} }
getMoreOrders() { getMoreOrders() {
this.lastViewOrder += 4; this.lastViewOrder += 4;
this.purchasesShortArray = this.purchases.slice(0, this.lastViewOrder); this.purchasesShortArray = this.filteredOfDatePurchases.slice(0, this.lastViewOrder);
} }
showPurchaseInfo(purchaseInfo: PurchaseInfo) { showPurchaseInfo(purchaseInfo: PurchaseInfo) {

View File

@ -0,0 +1,23 @@
import { Injectable } from '@angular/core';
import { NativeDateAdapter } from '@angular/material/core';
@Injectable({
providedIn: 'root',
})
export class DateAdapterService extends NativeDateAdapter {
override format(date: Date, displayFormat: Object): string {
if (displayFormat === 'input') {
let day: string = date.getDate().toString();
day = +day < 10 ? '0' + day : day;
let month: string = (date.getMonth() + 1).toString();
month = +month < 10 ? '0' + month : month;
let year = date.getFullYear();
return `${day}.${month}.${year}`;
}
return date.toLocaleDateString('ru-RU');
}
override getFirstDayOfWeek(): number {
return 1;
}
}

View File

@ -29,6 +29,13 @@ div.cdk-overlay-container {
z-index: 11200; z-index: 11200;
} }
.mat-form-field-type-mat-date-range-input .mat-form-field-infix {
display: flex;
align-items: center;
justify-content: space-between;
height: 41.67px;
}
.mat-snack-bar-container { .mat-snack-bar-container {
transform: scale(1); transform: scale(1);
opacity: 1; opacity: 1;