diff --git a/itenium-socks/angular.json b/itenium-socks/angular.json
index e7cfa50..788afa0 100644
--- a/itenium-socks/angular.json
+++ b/itenium-socks/angular.json
@@ -57,7 +57,13 @@
"development": {
"optimization": false,
"extractLicenses": false,
- "sourceMap": true
+ "sourceMap": true,
+ "fileReplacements": [
+ {
+ "replace": "src/environments/environment.ts",
+ "with": "src/environments/environment.development.ts"
+ }
+ ]
}
},
"defaultConfiguration": "production"
@@ -100,5 +106,8 @@
}
}
}
+ },
+ "cli": {
+ "analytics": false
}
}
diff --git a/itenium-socks/package-lock.json b/itenium-socks/package-lock.json
index 295c374..a0436b2 100644
--- a/itenium-socks/package-lock.json
+++ b/itenium-socks/package-lock.json
@@ -18,6 +18,7 @@
"@angular/router": "^18.0.0",
"@fortawesome/angular-fontawesome": "^0.15.0",
"@fortawesome/fontawesome-free": "^6.5.2",
+ "ngx-pagination": "^6.0.3",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
@@ -9054,6 +9055,18 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
+ "node_modules/ngx-pagination": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/ngx-pagination/-/ngx-pagination-6.0.3.tgz",
+ "integrity": "sha512-lONjTQ7hFPh1SyhwDrRd5ZwM4NMGQ7bNR6vLrs6mrU0Z8Q1zCcWbf/pvyp4DOlGyd9uyZxRy2wUsSZLeIPjbAw==",
+ "dependencies": {
+ "tslib": "^2.3.0"
+ },
+ "peerDependencies": {
+ "@angular/common": ">=13.0.0",
+ "@angular/core": ">=13.0.0"
+ }
+ },
"node_modules/nice-napi": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz",
diff --git a/itenium-socks/package.json b/itenium-socks/package.json
index 6b3a9d6..9da08d2 100644
--- a/itenium-socks/package.json
+++ b/itenium-socks/package.json
@@ -20,6 +20,7 @@
"@angular/router": "^18.0.0",
"@fortawesome/angular-fontawesome": "^0.15.0",
"@fortawesome/fontawesome-free": "^6.5.2",
+ "ngx-pagination": "^6.0.3",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
diff --git a/itenium-socks/public/images/placeholder.jpg b/itenium-socks/public/images/placeholder.jpg
new file mode 100644
index 0000000..9064588
Binary files /dev/null and b/itenium-socks/public/images/placeholder.jpg differ
diff --git a/itenium-socks/src/app/app.component.html b/itenium-socks/src/app/app.component.html
index 67e7bd4..6d00511 100644
--- a/itenium-socks/src/app/app.component.html
+++ b/itenium-socks/src/app/app.component.html
@@ -1 +1,6 @@
+@if(!isProduction){
+
+ WARNING: This is a non-production environment!
+
+}
diff --git a/itenium-socks/src/app/app.component.ts b/itenium-socks/src/app/app.component.ts
index 8ad7283..081903d 100644
--- a/itenium-socks/src/app/app.component.ts
+++ b/itenium-socks/src/app/app.component.ts
@@ -1,5 +1,6 @@
-import { Component } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
+import { environment } from '../environments/environment';
@Component({
selector: 'app-root',
@@ -9,4 +10,6 @@ import { RouterOutlet } from '@angular/router';
],
templateUrl: './app.component.html',
})
-export class AppComponent {}
+export class AppComponent{
+ isProduction = environment.production;
+}
diff --git a/itenium-socks/src/app/home/latest-socks.component.html b/itenium-socks/src/app/home/latest-socks.component.html
index 9cd2eb7..6362409 100644
--- a/itenium-socks/src/app/home/latest-socks.component.html
+++ b/itenium-socks/src/app/home/latest-socks.component.html
@@ -6,22 +6,24 @@
-
diff --git a/itenium-socks/src/app/home/latest-socks.component.ts b/itenium-socks/src/app/home/latest-socks.component.ts
index 9b03950..f817894 100644
--- a/itenium-socks/src/app/home/latest-socks.component.ts
+++ b/itenium-socks/src/app/home/latest-socks.component.ts
@@ -2,13 +2,14 @@ import { Component, OnInit } from '@angular/core';
import { SocksService } from '../socks/socks.service';
import { Observable } from 'rxjs';
import { Sock } from '../socks/sock.model';
-import { AsyncPipe, NgFor } from '@angular/common';
+import { AsyncPipe } from '@angular/common';
import { RouterLink } from '@angular/router';
+import { PricePipe } from '../price.pipe';
@Component({
selector: 'app-latest-socks',
standalone: true,
- imports: [NgFor, AsyncPipe, RouterLink],
+ imports: [AsyncPipe, RouterLink, PricePipe],
templateUrl: './latest-socks.component.html'
})
export class LatestSocksComponent implements OnInit {
diff --git a/itenium-socks/src/app/price.pipe.ts b/itenium-socks/src/app/price.pipe.ts
new file mode 100644
index 0000000..43e56c4
--- /dev/null
+++ b/itenium-socks/src/app/price.pipe.ts
@@ -0,0 +1,17 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'price',
+ standalone: true
+})
+export class PricePipe implements PipeTransform {
+
+ transform(value: number): string {
+ if (value) {
+ return `€${value.toFixed(2)}`;
+ } else {
+ return '€0.00';
+ }
+ }
+
+}
diff --git a/itenium-socks/src/app/socks/shop.component.html b/itenium-socks/src/app/socks/shop.component.html
index a0139e2..9c89adf 100644
--- a/itenium-socks/src/app/socks/shop.component.html
+++ b/itenium-socks/src/app/socks/shop.component.html
@@ -5,16 +5,33 @@
Our Socks
+
+
+
+
+
-
+
+
+
+
+
diff --git a/itenium-socks/src/app/socks/shop.component.ts b/itenium-socks/src/app/socks/shop.component.ts
index 33c897b..7424621 100644
--- a/itenium-socks/src/app/socks/shop.component.ts
+++ b/itenium-socks/src/app/socks/shop.component.ts
@@ -1,21 +1,83 @@
import { Component } from '@angular/core';
import { SocksService } from './socks.service';
-import { Observable } from 'rxjs';
+import { Observable,BehaviorSubject, combineLatest } from 'rxjs';
import { Sock } from './sock.model';
import { AsyncPipe, NgFor } from '@angular/common';
+import { NgxPaginationModule } from 'ngx-pagination';
+import { map } from 'rxjs/operators';
+import { PricePipe } from '../price.pipe';
@Component({
selector: 'app-shop',
standalone: true,
- imports: [NgFor, AsyncPipe],
+ imports: [NgFor, AsyncPipe, NgxPaginationModule, PricePipe],
templateUrl: './shop.component.html'
})
export class ShopComponent {
socks$!: Observable
;
+ filteredSocks$!: Observable;
+
+ public nameFilterSubject = new BehaviorSubject('');
+ public colorFilterSubject = new BehaviorSubject('');
+ public sortBySubject = new BehaviorSubject('name');
+ public currentPageSubject = new BehaviorSubject(1);
+ public pageSize = 10;
+
+ placeholderImageUrl = 'images/placeholder.jpg';
constructor(private socksService: SocksService) {}
ngOnInit(): void {
this.socks$ = this.socksService.get();
+
+ this.filteredSocks$ = combineLatest([
+ this.socks$,
+ this.nameFilterSubject.asObservable(),
+ this.colorFilterSubject.asObservable(),
+ this.sortBySubject.asObservable(),
+ this.currentPageSubject.asObservable()
+ ]).pipe(
+ map(([socks, nameFilter, colorFilter, sortBy, currentPage]) => {
+ let filtered = socks.filter(sock =>
+ sock.name.toLowerCase().includes(nameFilter.toLowerCase()) &&
+ sock.variant.toLowerCase().includes(colorFilter.toLowerCase())
+ );
+
+ filtered = filtered.sort((a, b) => {
+ if (sortBy === 'name') {
+ return a.name.localeCompare(b.name);
+ } else if (sortBy === 'price') {
+ return a.price - b.price;
+ }
+ return 0;
+ });
+
+ const startIndex = (currentPage - 1) * this.pageSize;
+ return filtered.slice(startIndex, startIndex + this.pageSize);
+ })
+ );
+ }
+
+ onFilterName(event: Event) {
+ const name = (event.target as HTMLInputElement).value;
+ this.nameFilterSubject.next(name);
+ }
+
+ onFilterColor(event: Event) {
+ const color = (event.target as HTMLInputElement).value;
+ this.colorFilterSubject.next(color);
+ }
+
+ onSortBy(event: Event) {
+ const sortBy = (event.target as HTMLInputElement).value;
+ this.sortBySubject.next(sortBy);
+ }
+
+ onPageChange(page: number) {
+ this.currentPageSubject.next(page);
+ }
+
+ onImageError(event: Event) {
+ (event.target as HTMLImageElement).src = this.placeholderImageUrl;
}
}
diff --git a/itenium-socks/src/app/socks/sock-reviews.component.html b/itenium-socks/src/app/socks/sock-reviews.component.html
index 696aab3..774dafd 100644
--- a/itenium-socks/src/app/socks/sock-reviews.component.html
+++ b/itenium-socks/src/app/socks/sock-reviews.component.html
@@ -17,7 +17,7 @@
{{ review.socksId }}
- On {{ review.added }} by {{ review.email }}
+ On {{ review.added | timeAgo }} by {{ review.email }}
diff --git a/itenium-socks/src/app/socks/sock-reviews.component.ts b/itenium-socks/src/app/socks/sock-reviews.component.ts
index fe89cb9..63722ca 100644
--- a/itenium-socks/src/app/socks/sock-reviews.component.ts
+++ b/itenium-socks/src/app/socks/sock-reviews.component.ts
@@ -3,11 +3,12 @@ import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { SocksService } from './socks.service';
import { Review } from './sock.model';
+import { TimeAgoPipe } from '../time-ago.pipe';
@Component({
selector: 'app-sock-reviews',
standalone: true,
- imports: [NgFor, AsyncPipe],
+ imports: [NgFor, AsyncPipe, TimeAgoPipe],
templateUrl: './sock-reviews.component.html'
})
export class SockReviewsComponent {
diff --git a/itenium-socks/src/app/time-ago.pipe.ts b/itenium-socks/src/app/time-ago.pipe.ts
new file mode 100644
index 0000000..1d1e3b9
--- /dev/null
+++ b/itenium-socks/src/app/time-ago.pipe.ts
@@ -0,0 +1,32 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'timeAgo',
+ standalone: true
+})
+export class TimeAgoPipe implements PipeTransform {
+
+ transform(value: number | Date | string): string {
+ if (!value) return 'N/A';
+
+ const time = new Date(value).getTime();
+ const now = new Date().getTime();
+ const difference = Math.floor((now - time) / 1000);
+
+ if (difference < 30) {
+ return 'Just now';
+ } else if (difference < 60) {
+ return 'A few seconds ago';
+ } else if (difference < 3600) {
+ const minutes = Math.floor(difference / 60);
+ return `${minutes} minute${minutes > 1 ? 's' : ''} ago`;
+ } else if (difference < 86400) {
+ const hours = Math.floor(difference / 3600);
+ return `${hours} hour${hours > 1 ? 's' : ''} ago`;
+ } else {
+ const days = Math.floor(difference / 86400);
+ return `${days} day${days > 1 ? 's' : ''} ago`;
+ }
+ }
+
+}
diff --git a/itenium-socks/src/environments/environment.development.ts b/itenium-socks/src/environments/environment.development.ts
new file mode 100644
index 0000000..ffe8aed
--- /dev/null
+++ b/itenium-socks/src/environments/environment.development.ts
@@ -0,0 +1,3 @@
+export const environment = {
+ production: false
+};
diff --git a/itenium-socks/src/environments/environment.ts b/itenium-socks/src/environments/environment.ts
new file mode 100644
index 0000000..3612073
--- /dev/null
+++ b/itenium-socks/src/environments/environment.ts
@@ -0,0 +1,3 @@
+export const environment = {
+ production: true
+};