Сделал менюху, сделал вывод заказов, некоторые правки
This commit is contained in:
gofnnp 2023-06-01 10:09:57 +04:00
parent ac7709b64e
commit cc5b1e4ba9
20 changed files with 459 additions and 102 deletions

View File

@ -3,7 +3,7 @@
"version": "0.0.1",
"scripts": {
"ng": "ng",
"start": "ng serve --host 192.168.0.14",
"start": "ng serve --host 192.168.0.14 --verbose",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"

View File

@ -1,13 +1,4 @@
{
"/api": {
"target": "https://apple-push-notifications.it-retail.tech/apns/api",
"secure": false,
"pathRewrite": {
"^/api": ""
},
"changeOrigin": true,
"logLevel": "debug"
},
"/icard-proxy": {
"target": "https://sakura.lk.crm4retail.ru/api/icard-proxy",
"secure": false,
@ -26,11 +17,11 @@
"changeOrigin": true,
"logLevel": "debug"
},
"/it-retail": {
"target": "https://sakura.lk.crm4retail.ru/it-retail",
"/api/orders": {
"target": "https://sakura.lk.crm4retail.ru/api/orders",
"secure": false,
"pathRewrite": {
"^/it-retail": ""
"^/api/orders": ""
},
"changeOrigin": true,
"logLevel": "debug"

View File

@ -37,13 +37,27 @@ export const PageListWithBonus: Page[] = [
resName: 'bonus-program',
onSideBar: false,
},
{
code: PageCode.Transactions,
name: 'Чеки',
description: '',
resName: 'transactions',
onSideBar: true,
},
{
code: PageCode.Orders,
name: 'Ваши чеки',
name: 'Заказы',
description: '',
resName: 'orders',
onSideBar: true,
},
{
code: PageCode.Logout,
name: 'Выйти',
description: '',
resName: 'logout',
onSideBar: true,
},
// {
// code: PageCode.UserData,
// name: 'Заполнить анкету',

View File

@ -80,6 +80,7 @@ import {MatNativeDateModule} from '@angular/material/core';
import { profileReducer } from './state/profile/profile.reducer';
import { ProfileEffects } from './state/profile/profile.effects';
import { CustomerInfoInterceptor } from './interceptors/customer-info.interceptor';
import { PurcahsesComponent } from './pages/account/purcahses/purcahses.component';
const routes: Routes = [
{ path: '', redirectTo: 'products', pathMatch: 'full' },
@ -120,6 +121,7 @@ const routes: Routes = [
SnackBarComponent,
PurchaseInfoComponent,
DateFilterComponent,
PurcahsesComponent,
],
imports: [
BrowserModule,

View File

@ -6,6 +6,8 @@ export enum PageCode {
Orders,
RefSystem,
UserData,
Transactions,
Logout
}
export enum MainPageCode {

View File

@ -11,67 +11,21 @@
[currentPage]="currentPage"
(deauthorization)="changePage(pageList[0])"
></app-bonus-program>
<!-- <div [ngSwitch]="currentPage.code" class="">
<ng-container *ngSwitchCase="PageCode.Orders">
<app-orders
[currentPage]="currentPage"
(deauthorization)="changePage(pageList[0])"
></app-orders>
</ng-container>
<ng-container *ngSwitchCase="PageCode.BonusProgram">
</ng-container>
<ng-container *ngSwitchCase="PageCode.UserData">
<app-user-data></app-user-data>
</ng-container>
<ng-container *ngSwitchCase="PageCode.RefSystem">
<app-ref-system></app-ref-system>
</ng-container>
</div> -->
<!-- <nav *ngIf="!showAuthoriztion" class="woocommerce-MyAccount-navigation">
<ul>
<ng-container *ngFor="let page of pageList; let index = index">
<li
*ngIf="page.onSideBar"
class="woocommerce-MyAccount-navigation-link"
[ngClass]="{
'is-active': page === currentPage,
first: index === 1
}"
(click)="changePage(page, $event)"
>
<div class="container">
<img
src="{{ './assets/menu-icons/' + page.resName + '.png' }}"
alt="Иконка меню"
/>
<div class="menu-item-info">
<a href="#">{{ page.name }}</a>
<p>{{ page.description }}</p>
</div>
</div>
</li>
</ng-container>
<li class="woocommerce-MyAccount-navigation-link" (click)="logout($event)">
<div class="container">
<img src="./assets/menu-icons/exit.png" alt="Иконка меню" />
<div class="menu-item-info">
<a href="#">Выход</a>
</div>
</div>
</li>
</ul>
</nav> -->
<mat-tab-group mat-stretch-tabs="false" mat-align-tabs="center">
<mat-tab-group mat-stretch-tabs="false" mat-align-tabs="center" (selectedTabChange)="changeTabPage($event)" [(selectedIndex)]="selectedTabPage">
<ng-container *ngFor="let page of pageList">
<mat-tab *ngIf="page.onSideBar" label="{{ page.name }}">
<div [ngSwitch]="page.resName" class="">
<ng-container *ngSwitchCase="'orders'">
<ng-container *ngSwitchCase="'transactions'">
<app-orders
[currentPage]="currentPage"
(deauthorization)="changePage(pageList[0])"
></app-orders>
</ng-container>
<ng-container *ngSwitchCase="'orders'">
<app-purcahses
></app-purcahses>
</ng-container>
<ng-container *ngSwitchCase="'user-data'">
<app-user-data></app-user-data>
</ng-container>

View File

@ -13,6 +13,7 @@ import { lastValueFrom } from 'rxjs';
import { CartService } from 'src/app/services/cart.service';
import { Store } from '@ngrx/store';
import { getProfile, getTransactions, getTransactionsInfo } from 'src/app/state/profile/profile.actions';
import { MatTabChangeEvent } from '@angular/material/tabs';
@Component({
selector: 'app-account',
@ -24,6 +25,7 @@ export class AccountComponent implements OnInit {
@Output() setUserDataOrderPage = new EventEmitter<null>();
@ViewChild('menu', { static: true}) menu!: ElementRef;
public refSystemId: string = '';
public selectedTabPage: number = 1
constructor(
private cookiesService: CookiesService,
@ -225,6 +227,13 @@ export class AccountComponent implements OnInit {
this.messageService.clear('c')
}
changeTabPage(event: MatTabChangeEvent) {
if (event.index === 2) {
this.selectedTabPage = 1
this.logout()
}
}
logout(event?: MouseEvent) {
if (event) {
event.preventDefault()

View File

@ -101,7 +101,7 @@
>
Показать больше
</p>
<p *ngIf="!purchasesShortArray.length && !ordersLoadingStatus" class="show-more-orders">
<p *ngIf="!purchasesShortArray.length && !ordersLoadingStatus" class="not-found-data">
Данные не найдены
</p>
<p-progressSpinner

View File

@ -4,6 +4,11 @@
color: var(--orange-main);
margin-top: 16px;
}
.not-found-data {
text-align: center;
color: var(--orange-main);
margin-top: 16px;
}
.woocommerce-MyAccount-content {
max-width: 400px;
margin-left: calc(50vw - 200px);

View File

@ -31,6 +31,7 @@ import {
getTransactions,
getTransactionsInfo,
} from 'src/app/state/profile/profile.actions';
import { MatSnackBar } from '@angular/material/snack-bar';
@Component({
selector: 'app-orders',
@ -60,7 +61,8 @@ export class OrdersComponent implements OnInit {
private wpJsonService: WpJsonService,
private cookiesService: CookiesService,
public dialog: MatDialog,
private store: Store
private store: Store,
private _snackBar: MatSnackBar
) {}
ngOnInit(): void {
@ -112,35 +114,96 @@ export class OrdersComponent implements OnInit {
return;
}
combineLatest([this.transactionsState$, this.transactionsInfoState$])
.pipe(distinctUntilChanged())
.subscribe({
next: ([transactions, transactionsInfo]) => {
if (transactions && transactionsInfo) {
this.purchases = transactions
.map<Purchase>((purchase) => {
return {
...purchase,
more_info:
transactionsInfo.find(
(purchaseInfo: PurchaseInfo) =>
Number(purchaseInfo.number) === purchase.orderNumber
) || null,
};
})
.filter((purchase: Purchase) =>
[
'PayFromWallet',
'CancelPayFromWallet',
'RefillWallet',
].includes(purchase.transactionType)
);
this.transactionsState$.subscribe({
next: (transactions) => {
// console.log(transactions);
if (transactions) {
this.purchases = transactions.filter((purchase: Purchase) =>
['PayFromWallet', 'CancelPayFromWallet', 'RefillWallet'].includes(
purchase.transactionType
)
);
this.ordersLoadingStatus = false
this.transactionsInfoState$.subscribe({
next: (transactionsInfo) => {
if (transactionsInfo) {
this.purchases.map<Purchase>((purchase) => {
return {
...purchase,
more_info:
transactionsInfo.find(
(purchaseInfo: PurchaseInfo) =>
Number(purchaseInfo.number) === purchase.orderNumber
) || null,
};
});
}
},
});
}
},
});
this.ordersLoadingStatus = false;
this.dateFilter({ filterType: this.defaultFilterType });
}
},
});
// combineLatest([this.transactionsState$, this.transactionsInfoState$])
// .pipe(distinctUntilChanged())
// .subscribe({
// next: ([transactions, transactionsInfo]) => {
// console.log('####: ', transactions);
// console.log('####I: ', transactionsInfo);
// if (transactions && transactionsInfo) {
// this.purchases = transactions
// .map<Purchase>((purchase) => {
// return {
// ...purchase,
// more_info:
// transactionsInfo.find(
// (purchaseInfo: PurchaseInfo) =>
// Number(purchaseInfo.number) === purchase.orderNumber
// ) || null,
// };
// })
// .filter((purchase: Purchase) =>
// [
// 'PayFromWallet',
// 'CancelPayFromWallet',
// 'RefillWallet',
// ].includes(purchase.transactionType)
// );
// } else if (transactions && !transactionsInfo) {
// this.purchases = transactions.filter((purchase: Purchase) =>
// ['PayFromWallet', 'CancelPayFromWallet', 'RefillWallet'].includes(
// purchase.transactionType
// )
// );
// this._snackBar.open(
// 'Произошла ошибка получения подробностей по транзакциям',
// '',
// {
// duration: 3500,
// }
// );
// } else {
// this._snackBar.open(
// 'Произошла ошибка получения данных по транзакциям',
// '',
// {
// duration: 3500,
// }
// );
// }
// this.ordersLoadingStatus = false;
// console.log(this.purchases);
// this.dateFilter({ filterType: this.defaultFilterType });
// },
// error: (err) => {
// console.error('Error: ', err);
// this.ordersLoadingStatus = false;
// },
// });
}
getMoreOrders() {

View File

@ -0,0 +1,140 @@
<div class="orders">
<!-- <h2>{{ currentPage.name }}</h2> -->
<table
class="woocommerce-orders-table woocommerce-MyAccount-orders shop_table shop_table_responsive my_account_orders account-orders-table"
>
<thead>
<tr>
<th
class="woocommerce-orders-table__header woocommerce-orders-table__header-order-date"
>
<span class="nobr">Дата</span>
</th>
<!-- <th
class="woocommerce-orders-table__header woocommerce-orders-table__header-order-status"
>
<span class="nobr">Место покупки</span>
</th> -->
<th
class="woocommerce-orders-table__header woocommerce-orders-table__header-order-total"
>
<span class="nobr">Сумма</span>
</th>
<th
class="woocommerce-orders-table__header woocommerce-orders-table__header-order-bonuses"
>
<span class="nobr">Статус</span>
</th>
<th
class="woocommerce-orders-table__header woocommerce-orders-table__header-order-actions"
>
<span class="nobr">Комментарий</span>
</th>
<th
class="woocommerce-orders-table__header woocommerce-orders-table__header-order-actions"
>
<span class="nobr">Магазин</span>
</th>
<th
class="woocommerce-orders-table__header woocommerce-orders-table__header-order-actions"
>
<span class="nobr">Продукты</span>
</th>
</tr>
</thead>
<tbody>
<tr
*ngFor="let purchase of purchases"
class="woocommerce-orders-table__row woocommerce-orders-table__row--status-processing order"
>
<td
class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-date"
data-title="Дата"
>
<time [dateTime]="purchase.created_datetime">{{
moment(purchase.created_datetime).format("DD.MM.YYYY")
}}</time>
</td>
<!-- <td
class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-status"
data-title="Место покупки"
>
{{ purchase.Address }}
</td> -->
<td
class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-total"
data-title="Сумма"
>
<span class="woocommerce-Price-amount amount">
{{ purchase.orderAmount }}
</span>
</td>
<td
*ngIf="purchase.status && orderStatuses[purchase.status]"
class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-total"
data-title="Статус"
>
<span class="woocommerce-Price-amount amount">
{{ orderStatuses[purchase.status] }}
</span>
</td>
<td
class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-total"
data-title="Комментарий"
>
<span class="woocommerce-Price-amount amount">
{{ purchase.data.comment }}
</span>
</td>
<!-- <td
class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-total"
data-title="Магазин"
>
<span class="woocommerce-Price-amount amount">
{{ purchase.data.comment }}
</span>
</td> -->
<td
*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>
</td>
</tr>
</tbody>
</table>
<!-- <p
*ngIf="
filteredOfDatePurchases.length !== purchasesShortArray.length &&
purchasesShortArray.length
"
class="show-more-orders"
(click)="getMoreOrders()"
>
Показать больше
</p>
<p
*ngIf="!purchasesShortArray.length && !ordersLoadingStatus"
class="not-found-data"
>
Данные не найдены
</p> -->
<p-progressSpinner
*ngIf="loading"
[style]="{ width: '100%' }"
strokeWidth="2"
styleClass="angular-spinner"
></p-progressSpinner>
<!-- <p
*ngIf="purchases.length === 0 && !ordersLoadingStatus"
style="width: 100%; text-align: center"
>
Нет заказов
</p> -->
</div>

View File

@ -0,0 +1,91 @@
.show-more-orders {
text-align: center;
cursor: pointer;
color: var(--orange-main);
margin-top: 16px;
}
.not-found-data {
text-align: center;
color: var(--orange-main);
margin-top: 16px;
}
.woocommerce-MyAccount-content {
max-width: 400px;
margin-left: calc(50vw - 200px);
}
.woocommerce-orders-table {
// border: 2px solid #dee2e6;
border-bottom: 0;
border-radius: 0.25rem;
border-collapse: separate;
text-align: left;
margin-top: 8px;
width: 100%;
// max-width: 400px;
margin-left: auto;
margin-right: auto;
thead {
display: none;
}
.woocommerce-orders-table {
&__cell {
padding: 0.7rem 1.5rem;
border-bottom: 2px solid #dee2e6;
text-align: right !important;
display: block;
min-height: 46px;
&::before {
content: attr(data-title) ": ";
font-weight: 700;
float: left;
}
}
&__row {
display: block;
&:nth-child(even) {
background: #ebebeb;
}
}
// &__cell-order-actions::before {
// display: none;
// }
&__cell-order-actions {
&.red-color {
color: #ed0000;
}
&.green-color {
color: #00a700;
}
}
&__cell-order-number a {
text-decoration: none;
color: #009688;
}
}
.woocommerce-button {
display: inline-block;
color: #ffffff;
background-color: #009688;
padding: 13px;
border-radius: 4px;
text-decoration: none;
width: 100%;
text-align: center;
}
}
:host {
.orders {
h2 {
font-style: normal;
font-weight: 700;
font-size: 20px;
line-height: 24px;
max-width: 400px;
margin: 0 auto;
width: 100%;
}
}
}

View File

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

View File

@ -0,0 +1,57 @@
import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import moment from 'moment';
import { orderStatuses } from 'src/app/app.constants';
import { PurchaseInfoComponent } from 'src/app/components/purchase-info/purchase-info.component';
import { PurchaseInfo } from 'src/app/interface/data';
import { WpJsonService } from 'src/app/services/wp-json.service';
import { environment } from 'src/environments/environment';
@Component({
selector: 'app-purcahses',
templateUrl: './purcahses.component.html',
styleUrls: ['./purcahses.component.scss'],
})
export class PurcahsesComponent implements OnInit {
public purchases: any;
readonly moment = moment;
public orderStatuses = orderStatuses;
public loading = true;
constructor(private wpJsonService: WpJsonService, public dialog: MatDialog) {}
ngOnInit(): void {
this.wpJsonService.getUserOrders(environment.webhookItRetail).subscribe({
next: (value) => {
this.purchases = value.result.map((purchase: any) => {
purchase.orderAmount = purchase.data.products.reduce(
(previous: any, current: any) => {
return previous + Number(current.amount);
},
0
);
purchase.more_info = {
date: purchase.created_datetime,
goods_list: purchase.data.products.map((product: any) => {
return {
name: product.name,
price: product.price,
quantity: product.quantity,
};
}),
number: purchase.public_id,
sum: purchase.orderAmount,
};
return purchase;
});
this.loading = false;
},
});
}
showPurchaseInfo(purchaseInfo: PurchaseInfo) {
const dialogRef = this.dialog.open(PurchaseInfoComponent, {
data: { purchaseInfo },
});
}
}

View File

@ -10,6 +10,7 @@ import { ActivatedRoute, Router } from '@angular/router';
import { MatBottomSheet } from '@angular/material/bottom-sheet';
import { TerminalListComponent } from 'src/app/components/terminal-list/terminal-list.component';
import { GetTerminalsService } from 'src/app/services/get-terminals.service';
import { environment } from 'src/environments/environment';
@Component({
selector: 'app-products',

View File

@ -167,7 +167,7 @@ export class OrderService {
submit(): Observable<any> {
return this.wpJsonService
.createOrder(this.order.toJson(), environment.webhookItRetail)
.createOrder(this.order.toJson(), `${environment.webhookItRetail}handlers/tillda/115eaf95-bb44-4cfc-851a-fec5325b45ff`)
.pipe(
tap({
next: (_) => {

View File

@ -70,12 +70,17 @@ export class WpJsonService {
return this._request(`/static/settings.json`, 'GET', null, false)
}
getUserOrders(url: string): Observable<any> {
return this._request(`/api/user/orders`, 'GET', null, true, url)
}
_request(path: string, method: string, body?: any, auth = false, baseUrl?: string): Observable<any> {
const token = decodeURI(this.cookiesService.getItem('token') ?? '');
let headers = new HttpHeaders();
headers = headers.set('Content-Type', 'application/json');
let urlToken = '';
if (token && token !== 'undefined' && auth) {
headers = headers.set('Authorization', `Bearer ${token}`)
urlToken = '?token=' + token;
}
this.body = body;

View File

@ -33,7 +33,7 @@ export class ProfileEffects {
throw new Error('Пользователь не найден в системе! Обратитесь к руководству')
}
if ('Error' in value) {
throw new Error('Ошибка получения данных');
throw new Error('Ошибка получения данных пользователя');
}
return {
getSuccessResponse: value,
@ -68,7 +68,7 @@ export class ProfileEffects {
throw new Error('Пользователь не найден в системе! Обратитесь к руководству')
}
if ('Error' in value) {
throw new Error('Ошибка получения данных');
throw new Error('Ошибка получения данных по транзакциям');
}
return {
getSuccessResponse: {
@ -105,7 +105,7 @@ export class ProfileEffects {
throw new Error('Пользователь не найден в системе! Обратитесь к руководству')
}
if ('Error' in value) {
throw new Error('Ошибка получения данных');
throw new Error('Ошибка получения данных подробностей по транзакциям');
}
return {
getSuccessResponse: {

View File

@ -20,7 +20,7 @@ export const environment = {
version: packageJson.version,
appleWalletEndpoint: 'https://apple-push-notifications.it-retail.tech/apns/api',
appleWalletSecret: 'Token F5mbzEERAznGKVbB6l',
webhookItRetail: 'https://sakura.lk.crm4retail.ru/api/orders/handlers/tillda/115eaf95-bb44-4cfc-851a-fec5325b45ff',
webhookItRetail: 'https://sakura.lk.crm4retail.ru/api/orders/',
icardProxy: 'https://sakura.lk.crm4retail.ru/api/icard-proxy/',
clientName: 'sakura',
cities: ['Менделеевск'],

View File

@ -20,7 +20,7 @@ export const environment = {
version: packageJson.version,
appleWalletEndpoint: 'http://192.168.0.179:4200/apns/api',
appleWalletSecret: 'Token F5mbzEERAznGKVbB6l',
webhookItRetail: 'http://192.168.0.14:4200/it-retail/handlers/tillda/1eb3fb56-3c4c-43b7-9a04-ce532ab7548f',
webhookItRetail: 'http://192.168.0.14:4200/api/orders',
icardProxy: 'http://192.168.0.14:4200/icard-proxy/',
clientName: 'sakura',
cities: ['Менделеевск'],