реализовал каталог товаров
This commit is contained in:
gofnnp 2022-10-28 21:11:05 +04:00
parent 694dbbfb8d
commit b5fd880379
10 changed files with 261 additions and 29 deletions

View File

@ -1 +1,19 @@
<p>checkbox-group works!</p>
<div *ngFor="let option of options" class="extra_options_checkbox">
<div class="extra_options_label"><label>{{option.name}}</label></div>
<div class="extra_options_value">
<div class="woofood-cbx-wrapper">
<input class="inp-woofood-cbx"
[disabled]="!optionIsSelected(option) && selectedOptions.length >= modifier.restrictions.maxQuantity"
[checked]="optionIsSelected(option)" type="checkbox" style="display: none" name="add_extra_option"
value="{{option.id}}" id="{{option.id}}" (change)="onToggle(option)">
<label class="woofood-cbx" for="{{option.id}}">
<span>
<svg width="12px" height="10px" viewBox="0 0 12 10">
<polyline points="1.5 6 4.5 9 10.5 1"></polyline>
</svg>
</span>
<span>{{currencySymbol}}{{0}}</span>
</label>
</div>
</div>
</div>

View File

@ -0,0 +1,89 @@
:host {
.extra_options_checkbox {
width: 100%;
display: block;
overflow: hidden;
display: flex;
align-items: center;
.extra_options_label {
width: 70%;
float: left;
font-size: 14px;
label {
margin: 5px;
font-weight: normal;
}
}
.extra_options_value {
width: 30%;
float: left;
.woofood-cbx-wrapper {
width: 100%;
float: left;
.woofood-cbx {
margin: auto;
-webkit-user-select: none;
user-select: none;
cursor: pointer;
line-height: 30px;
margin-bottom: 0px;
span:first-child {
display: inline-block;
position: relative;
width: 18px;
height: 18px;
margin-right: 8px;
border-radius: 3px;
transform: scale(1);
vertical-align: middle;
border: 1px solid #9098A9;
transition: all 0.2s ease;
&::before {
content: "";
width: 100%;
height: 100%;
background: #cc0000;
display: block;
transform: scale(0);
opacity: 1;
border-radius: 50%;
}
svg {
position: absolute;
top: 3px;
left: 2px;
fill: none;
stroke: #FFFFFF;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
stroke-dasharray: 16px;
stroke-dashoffset: 16px;
}
}
}
}
}
.inp-woofood-cbx:checked+.woofood-cbx span:first-child {
background: #cc0000;
border-color: #cc0000;
animation: wave 0.4s ease;
svg {
stroke-dashoffset: 0 !important;
}
}
.inp-woofood-cbx:disabled+.woofood-cbx span:first-child {
border-color: #dfdfdf !important;
}
}
}

View File

@ -1,5 +1,5 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {Modifier, Option} from 'src/app/interface/data';
import {Modifier, ModifiersGroup, Option} from 'src/app/interface/data';
import { cloneDeep } from 'lodash/fp';
@Component({
@ -11,23 +11,22 @@ export class CheckboxGroupComponent implements OnInit {
constructor() { }
@Input() modifier!: Modifier;
@Input() modifier!: ModifiersGroup;
@Input() options!: Modifier[];
@Input() currencySymbol!: string;
@Output() toggle = new EventEmitter<Option>();
@Output() toggle = new EventEmitter<Modifier>();
@Input() selectedOptions: Option[] = [];
public options: Option[] = [];
@Input() selectedOptions: Modifier[] = [];
ngOnInit() {
// this.options = cloneDeep<Option[]>(this.modifier.options);
}
optionIsSelected(option: Option): boolean{
optionIsSelected(option: Modifier): boolean{
return !!this.selectedOptions.find(selected => selected.id === option.id);
}
onToggle(option: Option){
onToggle(option: Modifier){
this.toggle.emit(option);
}

View File

@ -4,18 +4,30 @@
<div class="product-modal__modifiers-container">
<ng-container *ngIf="product.modifiers_group.length">
<div *ngFor="let modifier of modifiersFilter()" class="product-card__modifier">
<h4>{{modifier.name}}</h4>
<!-- <app-checkbox-group [modifier]="modifier" currencySymbol="₽"
[selectedOptions]="selectedOptions(modifier)" (toggle)="addOption(modifier, $event)">
</app-checkbox-group> -->
<div *ngFor="let modifierGroup of modifiersFilter()" [attr.isShow]="false" class="product-modal__modifier" #modifierContainer>
<a (click)="setOptionsView($event, modifierContainer)">
{{modifierGroup.name}}
<span [ngClass]="{
'product-modal__modifier-icon': true,
'isShow': getIsShow(modifierContainer)
}"></span>
</a>
<div [ngClass]="{
'options-container': true,
'isShow': getIsShow(modifierContainer)
}">
<app-checkbox-group [modifier]="modifierGroup" [options]="optionsFilter(modifierGroup)"
currencySymbol="₽" [selectedOptions]="selectedOptions(modifierGroup)"
(toggle)="addOption(modifierGroup, $event)">
</app-checkbox-group>
</div>
</div>
</ng-container>
</div>
<div class="product-modal__footer">
<span>{{product.price}}₽</span>
<button class="product-modal__add-to-cart">
<span class="product-modal__footer-price">{{product.price}}₽</span>
<button class="product-modal__add-to-cart" (click)="addToCart($event)">
Добавить
</button>
</div>

View File

@ -2,7 +2,8 @@
.product-modal {
position: relative;
padding-bottom: 60px;
& > img {
&>img {
width: 100%;
}
@ -18,6 +19,12 @@
justify-content: space-between;
align-items: center;
}
&__footer-price {
font-size: 18px;
font-weight: 600;
}
&__add-to-cart {
padding: 8px;
border: none;
@ -25,5 +32,53 @@
background-color: #0d457e;
color: #fff;
}
&__modifier {
border: 1px solid rgba(128, 128, 128, 0.23);
margin: 0.5em 0;
padding-bottom: 6px;
a {
width: 100%;
display: block;
padding: 0.75em;
border-radius: 0.15em;
transition: background .3s ease;
}
.options-container {
transition: opacity .5s ease;
padding-left: 16px;
display: none;
opacity: 0;
&.isShow {
display: block;
opacity: 1;
}
}
}
&__modifier-icon {
float: right;
&::before, &::after {
display: inline-block;
font-size: 14px;
transition: transform .5s ease;
}
&::before {
content: "\\";
transform: rotate(346deg);
}
&::after {
content: "/";
transform: rotate(14deg);
}
&.isShow {
&::before {
transform: rotate(76deg);
}
&::after {
transform: rotate(104deg);
}
}
}
}
}

View File

@ -1,6 +1,8 @@
import { Component, OnInit } from '@angular/core';
import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog';
import { AllData, Modifier, ModifiersGroup, Product } from 'src/app/interface/data';
import { AllData, Modifier, ModifiersGroup, Option, Product } from 'src/app/interface/data';
import { CartProduct } from 'src/app/models/cart-product';
import { CartService } from 'src/app/services/cart.service';
import { WpJsonService } from 'src/app/services/wp-json.service';
@Component({
@ -13,24 +15,66 @@ export class ProductModalComponent implements OnInit {
public allData!: AllData;
public modifiersGroups!: ModifiersGroup[];
public modifiers!: Modifier[];
public cartProduct!: CartProduct;
constructor(
public dialogRef: DynamicDialogRef,
public config: DynamicDialogConfig,
private wpJsonService: WpJsonService
private wpJsonService: WpJsonService,
private cartService: CartService,
) { }
ngOnInit(): void {
this.product = this.config.data.product
this.modifiersGroups = this.config.data.modifiersGroups
this.modifiers = this.config.data.modifiers
this.modifiers = this.config.data.modifiers
this.cartProduct = new CartProduct(this.product.id, this.product.name, this.modifiersFilter(), this.modifiers);
}
modifiersFilter() {
modifiersFilter(): ModifiersGroup[] {
return this.modifiersGroups.filter((value) => this.product.modifiers_group.includes(value.id))
}
// selectedOptions(modifier: Modifier): Option[]{
// return this.cartProduct.modifiers.find(cartModifier => cartModifier.id === modifier.id)?.options ?? [];
// }
optionsFilter(modifierGroup: ModifiersGroup): Modifier[] {
return this.modifiers.filter((modifier) => modifier.groupId === modifierGroup.id)
}
selectedOptions(modifier: ModifiersGroup): Modifier[]{
return this.cartProduct.modifiers.find(cartModifier => cartModifier.id === modifier.id)?.options ?? [];
}
addOption(modifier: ModifiersGroup, option: Modifier){
const modif = this.cartProduct.modifiers.find((modif) => modif.id === modifier.id);
const optionSelectedCartIndex = modif?.options.findIndex((modif) => modif.id === option.id)
if ((optionSelectedCartIndex || optionSelectedCartIndex === 0) && optionSelectedCartIndex !== -1) {
modif?.options.splice(optionSelectedCartIndex, 1)
return
}
modif?.options.push(option)
}
getIsShow(element: HTMLDivElement) {
const isShow = Object.values(element.attributes).find((value) => value.name === 'isshow')?.value
return isShow === 'true'
}
setOptionsView(event: Event, element: HTMLDivElement) {
if (event) {
event.preventDefault()
}
const isShow = this.getIsShow(element)
if (isShow) {
element.setAttribute('isShow', 'false')
return
}
element.setAttribute('isShow', 'true')
}
addToCart(event: Event) {
if (event) {
event.preventDefault()
}
this.cartService.addToCart(this.cartProduct);
this.dialogRef.close();
}
}

View File

@ -1,5 +1,8 @@
<div class="products-container">
<p-listbox [options]="groups" [(ngModel)]="selectedGroup" optionLabel="name" [style]="{'width':'fit-content', 'margin-bottom': '16px'}"></p-listbox>
<div class="products-container__filters-container">
<p-treeSelect [(ngModel)]="selectedGroup" [options]="groups" placeholder="Группа"></p-treeSelect>
</div>
<div class="products-container__items">
<div *ngFor="let product of filterByGroup()" class="products-container__item">
<img *ngIf="!product.image" src="./assets/no-image.png" alt="{{product.name}}">

View File

@ -5,12 +5,24 @@
flex-direction: column;
margin-bottom: 16px;
&__filters-container {
width: 100%;
max-width: 700px;
margin: 12px auto 24px auto;
display: flex;
flex-wrap: nowrap;
justify-content: space-between;
flex-direction: row;
}
&__items {
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 16px;
max-width: 700px;
margin: 0 auto;
}
&__item {

View File

@ -15,7 +15,7 @@ export class ProductsComponent implements OnInit {
public groups: Group[] = [
{
id: uuidv4(),
name: 'Все'
label: 'Все'
}
];
public modifiersGroups!: ModifiersGroup[];
@ -43,7 +43,7 @@ export class ProductsComponent implements OnInit {
}
filterByGroup() {
if (this.selectedGroup.name === 'Все') return this.products
if (this.selectedGroup.label === 'Все') return this.products
return this.products.filter((product) => product.groupId === this.selectedGroup.id)
}

View File

@ -1,7 +1,7 @@
{
"groups": [
{
"name": "тестовая категория",
"label": "тестовая категория",
"id": "05126d92-0e17-4c0f-b4c3-db6a9a1afdeb"
}
],
@ -66,7 +66,7 @@
"id": "00000000-0000-0000-0000-000000000000",
"restrictions": {
"minQuantity": 0,
"maxQuantity": 0,
"maxQuantity": 1,
"freeQuantity": 0,
"byDefault": 0
}