import { Component } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { Observable } from 'rxjs';
import { map, startWith } from 'rxjs/operators';
export interface Item {
id: number;
category: string;
name: string;
rating: number;
image: string;
description: string;
available: boolean;
size: string[] | number[];
condition: string;
color: string;
price: number;
discount: number;
gender: string;
keywords?: string[];
}
export interface Filters {
sale: string | null;
sort: string | null;
color: string | null;
conditionNew: boolean | null;
conditionUsed: boolean | null;
conditionCollectible: boolean | null;
conditionRenewed: boolean | null;
rating: number | null;
price: number | null;
size34: number | null;
size36: number | null;
size38: number | null;
size40: number | null;
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
filteredItems$: Observable<Item[]>;
filtersGroup: FormGroup;
defaultFilters: Filters = {
color: null,
sale: null,
sort: null,
conditionNew: null,
conditionUsed: null,
conditionCollectible: null,
conditionRenewed: null,
rating: null,
price: null,
size34: null,
size36: null,
size38: null,
size40: null,
};
options = [
{ value: 'ratingdesc', label: 'Best rating' },
{ value: 'pricedesc', label: 'Higest price first' },
{ value: 'priceasc', label: 'Lowest price first' },
];
noItemsFound = false;
items: Item[] = [
{
id: 1,
category: 'shirts',
name: 'Fantasy T-shirt',
rating: 4,
image:
'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/12.webp',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
available: true,
size: ['34', '36', '40'],
condition: 'new',
color: 'blue',
price: 12.99,
keywords: ['t-shirt', 'sweatshitrt'],
discount: 0,
gender: 'male',
},
{
id: 2,
category: 'shirts',
name: 'Fantasy T-shirt',
rating: 5,
image:
'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/13.webp',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
available: true,
size: ['34', '36', '40', '44'],
condition: 'new',
color: 'red',
price: 12.99,
discount: 0,
gender: 'male',
},
{
id: 3,
category: 'shirts',
name: 'Fantasy T-shirt',
rating: 3,
image:
'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/14.webp',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
available: true,
size: ['34', '36'],
condition: 'new',
color: 'grey',
price: 40.99,
discount: 10,
gender: 'male',
},
{
id: 4,
category: 'jackets',
name: 'Denim Jacket',
rating: 5,
size: [],
image:
'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/15.webp',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
available: true,
condition: 'new',
color: 'grey',
price: 40.99,
discount: 0,
gender: 'unisex',
},
{
id: 5,
category: 'jeans',
name: 'Ripped jeans',
rating: 5,
image:
'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/11.webp',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
available: true,
size: ['34', '36', '38', '40'],
condition: 'renewed',
color: 'blue',
price: 20.99,
discount: 5,
gender: 'female',
},
{
id: 6,
category: 'jeans',
name: 'Boyfriend jeans',
rating: 4,
image:
'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/10.webp',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
available: false,
size: ['34', '36', '38', '40'],
condition: 'used',
color: 'blue',
price: 20.99,
discount: 5,
gender: 'female',
},
{
id: 7,
category: 'shirts',
name: 'Ripped sweatshirt',
rating: 4,
image:
'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/7.webp',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
available: true,
size: ['34', '36', '38', '40'],
condition: 'collectible',
color: 'white',
price: 29.99,
discount: 5,
gender: 'female',
},
{
id: 8,
category: 'shirts',
name: 'Longsleeve',
rating: 4,
image:
'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/8.webp',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
available: true,
size: ['40'],
condition: 'collectible',
color: 'black',
price: 120.99,
discount: 0,
gender: 'male',
},
{
id: 8,
category: 'shirts',
name: 'Stripped sweatshirt',
rating: 4,
image:
'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/6.webp',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
available: true,
size: ['40', '38', '36'],
condition: 'new',
color: 'white',
price: 32.99,
discount: 10,
gender: 'female',
},
{
id: 9,
category: 'trousers',
name: 'Red chinos',
rating: 5,
image:
'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/5.webp',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
available: true,
size: ['40', '38', '36'],
condition: 'new',
color: 'red',
price: 62.99,
discount: 10,
gender: 'female',
},
{
id: 10,
category: 'coats',
name: 'Camel coat',
rating: 5,
image:
'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/4.webp',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
available: true,
size: ['40', '38', '36'],
condition: 'used',
color: 'brown',
price: 62.99,
discount: 10,
gender: 'female',
},
{
id: 11,
category: 'jeans',
name: 'Blue jeans',
rating: 5,
image:
'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/3.webp',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
available: true,
size: ['40', '38', '36'],
condition: 'new',
color: 'blue',
price: 42.99,
discount: 0,
gender: 'female',
},
{
id: 12,
category: 'shirts',
name: 'Orange T-shirt',
rating: 3,
image:
'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/3.webp',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
available: true,
size: ['40', '38', '36'],
condition: 'new',
color: 'orange',
price: 12.99,
discount: 0,
gender: 'female',
},
{
id: 13,
category: 'skirts',
name: 'Ballerina skirt',
rating: 4,
image:
'https://mdbcdn.b-cdn.net/img/Photos/Horizontal/E-commerce/Vertical/2.webp',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Numquam, sapiente illo. Sit error voluptas repellat rerum quidem, soluta enim perferendis voluptates laboriosam.',
available: true,
size: ['38', '36'],
condition: 'collectible',
color: 'white',
price: 12.99,
discount: 0,
gender: 'female',
},
];
constructor() {
this.filtersGroup = new FormGroup({
color: new FormControl(),
sale: new FormControl(),
conditionNew: new FormControl(),
conditionUsed: new FormControl(),
conditionCollectible: new FormControl(),
conditionRenewed: new FormControl(),
rating: new FormControl(),
price: new FormControl(),
size34: new FormControl(),
size36: new FormControl(),
size38: new FormControl(),
size40: new FormControl(),
sort: new FormControl()
});
this.filteredItems$ = this.filtersGroup.valueChanges.pipe(
startWith(this.defaultFilters),
map((controls: Filters) => {
const { rating, price, color, sort } = controls;
let items = this.items;
const conditions = Object.keys(controls)
.filter(
(control) =>
controls[control as keyof Filters] &&
control.startsWith('condition')
)
.map((string) => string.toLowerCase().replace('condition', ''));
if (conditions.length > 0) {
items = items.filter((item) =>
conditions.some((condition) => item.condition === condition)
);
}
if (rating) {
items = items.filter((item) => item['rating'] === rating)
}
if (price) {
if (price.toString().startsWith('<')) {
items = items.filter((item) => item['price'] < Number(price.toString().split('<')[1]));
}
if (price.toString().startsWith('>')) {
items = items.filter((item) => item['price'] > Number(price.toString().split('>')[1]));
}
if (price.toString().split('-').length === 2) {
items = items.filter((item) => item['price'] > Number(price.toString().split('-')[0]) && item['price'] < Number(price.toString().split('-')[1]))
}
}
const sizes = Object.keys(controls)
.filter(
(control) =>
controls[control as keyof Filters] &&
control.startsWith('size')
)
.map((string) => Number(string.toLowerCase().replace('size', '')));
this.noItemsFound = false;
if (sizes.length > 0) {
items = items.filter((item) =>
sizes.some((checkboxSize) => item['size'].some((itemSize) => itemSize === checkboxSize.toString()))
);
}
if (color) {
console.log(color)
items = items.filter((item) => item['color'] === color);
}
if (sort && sort.startsWith('price')) {
items = items.sort((a, b) =>
sort.endsWith('asc') ? a['price'] - b['price'] : b['price'] - a['price']
);
}
if (sort && sort.startsWith('rating')) {
items = items.sort((a, b) =>
sort.endsWith('asc') ? a['rating'] - b['rating'] : b['rating'] - a['rating']
);
}
if (items.length < 1) {
this.noItemsFound = true;
}
return items;
})
);
}
clearFilters() {
this.filtersGroup.reset();
}
}