From 7f96fa45034dbd31104f3d3a5db475a7cc6bf491 Mon Sep 17 00:00:00 2001 From: gofnnp Date: Thu, 30 Mar 2023 11:13:35 +0400 Subject: [PATCH] =?UTF-8?q?dev=20#13992=20=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0?= =?UTF-8?q?=D0=BB=20=D1=84=D0=B8=D0=BB=D1=8C=D1=82=D1=80=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8E=20=D0=BF=D0=BE=20=D0=B4=D0=B0=D1=82=D0=B5,=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=BA=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0=D0=BB=20?= =?UTF-8?q?=D0=BA=D0=B0=D0=BB=D0=B5=D0=BD=D0=B4=D0=B0=D1=80=D1=8C=20=D0=BD?= =?UTF-8?q?=D0=B0=20=D1=80=D1=83=D1=81=D1=81=D0=BA=D0=B8=D0=B9=20=D1=8F?= =?UTF-8?q?=D0=B7=D1=8B=D0=BA=20=D0=B8=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0?= =?UTF-8?q?=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- angular/src/app/app.constants.ts | 229 ++++++++++-------- angular/src/app/app.module.ts | 8 +- .../date-filter/date-filter.component.html | 43 ++++ .../date-filter/date-filter.component.scss | 28 +++ .../date-filter/date-filter.component.spec.ts | 23 ++ .../date-filter/date-filter.component.ts | 70 ++++++ angular/src/app/interface/data.ts | 11 + .../account/orders/orders.component.html | 30 ++- .../pages/account/orders/orders.component.ts | 42 +++- .../src/app/services/date-adapter.service.ts | 23 ++ angular/src/styles.scss | 7 + 11 files changed, 408 insertions(+), 106 deletions(-) create mode 100644 angular/src/app/components/date-filter/date-filter.component.html create mode 100644 angular/src/app/components/date-filter/date-filter.component.scss create mode 100644 angular/src/app/components/date-filter/date-filter.component.spec.ts create mode 100644 angular/src/app/components/date-filter/date-filter.component.ts create mode 100644 angular/src/app/services/date-adapter.service.ts diff --git a/angular/src/app/app.constants.ts b/angular/src/app/app.constants.ts index 7bf7127..3cc2229 100644 --- a/angular/src/app/app.constants.ts +++ b/angular/src/app/app.constants.ts @@ -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[] = [ - // { - // code: PageCode.Auth, - // name: 'Вход', - // resName: 'auth', - // onSideBar: false, - // }, - { - code: PageCode.Orders, - name: 'Заказы', - resName: 'orders', - onSideBar: true, - }, + // { + // code: PageCode.Auth, + // name: 'Вход', + // resName: 'auth', + // onSideBar: false, + // }, + { + code: PageCode.Orders, + name: 'Заказы', + resName: 'orders', + onSideBar: true, + }, ]; export const PageListWithBonus: Page[] = [ - // { - // code: PageCode.Auth, - // name: 'Вход', - // resName: 'auth', - // onSideBar: false, - // }, - { - code: PageCode.BonusProgram, - name: 'Ваша карта лояльности', - description: '', - resName: 'bonus-program', - onSideBar: false, - }, - { - code: PageCode.Orders, - name: 'Ваши чеки', - description: '', - resName: 'orders', - onSideBar: true, - }, - // { - // code: PageCode.UserData, - // name: 'Заполнить анкету', - // description: '', - // resName: 'user-data', - // onSideBar: true - // }, - // { - // code: PageCode.RefSystem, - // name: 'Пригласить друга', - // description: '', - // resName: 'ref-system', - // onSideBar: true, - // }, + // { + // code: PageCode.Auth, + // name: 'Вход', + // resName: 'auth', + // onSideBar: false, + // }, + { + code: PageCode.BonusProgram, + name: 'Ваша карта лояльности', + description: '', + resName: 'bonus-program', + onSideBar: false, + }, + { + code: PageCode.Orders, + name: 'Ваши чеки', + description: '', + resName: 'orders', + onSideBar: true, + }, + // { + // code: PageCode.UserData, + // name: 'Заполнить анкету', + // description: '', + // resName: 'user-data', + // onSideBar: true + // }, + // { + // code: PageCode.RefSystem, + // name: 'Пригласить друга', + // description: '', + // resName: 'ref-system', + // onSideBar: true, + // }, ]; export const PageListMain: Page[] = [ - { - code: MainPageCode.Account, - name: 'Аккаунт', - resName: 'account', - onSideBar: true, - icon: 'person' - }, - { - code: MainPageCode.Products, - name: 'Товары', - resName: 'products', - onSideBar: true, - icon: 'manage_search' - }, - { - code: MainPageCode.Cart, - name: 'Корзина', - resName: 'cart', - onSideBar: true, - icon: 'shopping_bag' - }, - // { - // code: MainPageCode.Info, - // name: 'О нас', - // resName: 'info', - // onSideBar: true, - // icon: 'info' - // }, -] + { + code: MainPageCode.Account, + name: 'Аккаунт', + resName: 'account', + onSideBar: true, + icon: 'person', + }, + { + code: MainPageCode.Products, + name: 'Товары', + resName: 'products', + onSideBar: true, + icon: 'manage_search', + }, + { + code: MainPageCode.Cart, + name: 'Корзина', + resName: 'cart', + onSideBar: true, + icon: 'shopping_bag', + }, + // { + // code: MainPageCode.Info, + // name: 'О нас', + // resName: 'info', + // onSideBar: true, + // icon: 'info' + // }, +]; export const orderStatuses: OrderStatus = { - 'Cancelled': 'Отменен', - 'InProcessing': 'В обработке', - 'Unconfirmed': 'Принят', - 'WaitCooking': 'Принят', - 'ReadyForCooking': 'Принят', - 'CookingStarted': 'Готовится', - 'CookingCompleted': 'Приготовлен', - 'Waiting': 'В пути', - 'OnWay': 'В пути', - 'Delivered': 'Выполнен', - 'Closed': 'Выполнен', + Cancelled: 'Отменен', + InProcessing: 'В обработке', + Unconfirmed: 'Принят', + WaitCooking: 'Принят', + ReadyForCooking: 'Принят', + CookingStarted: 'Готовится', + CookingCompleted: 'Приготовлен', + Waiting: 'В пути', + OnWay: 'В пути', + Delivered: 'Выполнен', + Closed: 'Выполнен', }; -export const paymentMethods: PaymentMethod[] = [ - { - type: 'Card', - label: 'Безналичный расчет' - }, - { - type: 'Cash', - label: 'Наличными' - } - ] \ No newline at end of file +export const paymentMethods: PaymentMethod[] = [ + { + type: 'Card', + label: 'Безналичный расчет', + }, + { + type: 'Cash', + 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' }, + }, +}; diff --git a/angular/src/app/app.module.ts b/angular/src/app/app.module.ts index a70308e..ceccb84 100644 --- a/angular/src/app/app.module.ts +++ b/angular/src/app/app.module.ts @@ -74,6 +74,9 @@ import { MatSnackBarModule } from '@angular/material/snack-bar'; import { SnackBarComponent } from './components/snack-bar/snack-bar.component'; import {MatDialogModule} from '@angular/material/dialog'; 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 = [ { path: '', redirectTo: 'products', pathMatch: 'full' }, @@ -113,6 +116,7 @@ const routes: Routes = [ TerminalListComponent, SnackBarComponent, PurchaseInfoComponent, + DateFilterComponent, ], imports: [ BrowserModule, @@ -162,7 +166,9 @@ const routes: Routes = [ MatButtonModule, MatListModule, MatSnackBarModule, - MatDialogModule + MatDialogModule, + MatDatepickerModule, + MatNativeDateModule ], providers: [ DialogService, diff --git a/angular/src/app/components/date-filter/date-filter.component.html b/angular/src/app/components/date-filter/date-filter.component.html new file mode 100644 index 0000000..ec3e6fb --- /dev/null +++ b/angular/src/app/components/date-filter/date-filter.component.html @@ -0,0 +1,43 @@ +
+
+ + + {{ + option.name + }} + + Фильтр + Тип + +
+ + Интервал времени + + + + + дд.мм.гггг – дд.мм.гггг + + + + + + + + +
+ +
+
diff --git a/angular/src/app/components/date-filter/date-filter.component.scss b/angular/src/app/components/date-filter/date-filter.component.scss new file mode 100644 index 0000000..c799814 --- /dev/null +++ b/angular/src/app/components/date-filter/date-filter.component.scss @@ -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; +} diff --git a/angular/src/app/components/date-filter/date-filter.component.spec.ts b/angular/src/app/components/date-filter/date-filter.component.spec.ts new file mode 100644 index 0000000..32cf766 --- /dev/null +++ b/angular/src/app/components/date-filter/date-filter.component.spec.ts @@ -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; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DateFilterComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(DateFilterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/angular/src/app/components/date-filter/date-filter.component.ts b/angular/src/app/components/date-filter/date-filter.component.ts new file mode 100644 index 0000000..aec5f39 --- /dev/null +++ b/angular/src/app/components/date-filter/date-filter.component.ts @@ -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(); + @Input() options!: IOptionDateFilter[]; + + public currentFilterType!: string; + + public dateFilterForm = new FormGroup({ + filterType: new FormControl(''), + from: new FormControl(null), + to: new FormControl(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) + } +} diff --git a/angular/src/app/interface/data.ts b/angular/src/app/interface/data.ts index 3b093fd..997b90e 100644 --- a/angular/src/app/interface/data.ts +++ b/angular/src/app/interface/data.ts @@ -275,3 +275,14 @@ export interface ITerminal { label: string; id: string; } + +export interface IOptionDateFilter { + name: string; + value: string; +} + +export interface IDateFilter { + filterType: string; + from?: Date; + to?: Date; +} diff --git a/angular/src/app/pages/account/orders/orders.component.html b/angular/src/app/pages/account/orders/orders.component.html index ad4391c..510f2b5 100644 --- a/angular/src/app/pages/account/orders/orders.component.html +++ b/angular/src/app/pages/account/orders/orders.component.html @@ -1,3 +1,9 @@ + +
{{ purchase.transactionSum }} - @@ -78,12 +95,15 @@
- +

Показать больше

+

+ Данные не найдены +

{ + 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() { const token = this.cookiesService.getItem('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; } getMoreOrders() { this.lastViewOrder += 4; - this.purchasesShortArray = this.purchases.slice(0, this.lastViewOrder); + this.purchasesShortArray = this.filteredOfDatePurchases.slice(0, this.lastViewOrder); } showPurchaseInfo(purchaseInfo: PurchaseInfo) { diff --git a/angular/src/app/services/date-adapter.service.ts b/angular/src/app/services/date-adapter.service.ts new file mode 100644 index 0000000..f75bfb8 --- /dev/null +++ b/angular/src/app/services/date-adapter.service.ts @@ -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; + } +} diff --git a/angular/src/styles.scss b/angular/src/styles.scss index 7560685..ed94b0a 100644 --- a/angular/src/styles.scss +++ b/angular/src/styles.scss @@ -29,6 +29,13 @@ div.cdk-overlay-container { 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 { transform: scale(1); opacity: 1;