feature: show order summary on address page
This commit is contained in:
parent
419e8281e2
commit
bb3aafd89e
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"angular-cli": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"@angular/cli",
|
||||||
|
"mcp"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,12 +4,45 @@
|
|||||||
<div class="grid grid-cols-3 gap-x-10">
|
<div class="grid grid-cols-3 gap-x-10">
|
||||||
<div class="col-span-2 flex flex-col space-y-4">
|
<div class="col-span-2 flex flex-col space-y-4">
|
||||||
@for (address of addresses(); track address.id) {
|
@for (address of addresses(); track address.id) {
|
||||||
<app-address-select [address]="address" (addressUpdated)="updateAddress($event)" />
|
<div class="flex space-x-2">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="address"
|
||||||
|
value="{{address.id}}"
|
||||||
|
[formControl]="addressIdControl"
|
||||||
|
/>
|
||||||
|
<app-address-select
|
||||||
|
class="flex-1"
|
||||||
|
[address]="address"
|
||||||
|
(addressUpdated)="updateAddress($event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
<app-address-form (submitAddress)="createNewAddress($event)" />
|
<app-address-form class="ml-5" (submitAddress)="createNewAddress($event)" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<app-order-summery />
|
<app-order-summery />
|
||||||
|
<div class="card mt-4">
|
||||||
|
<fieldset class="fieldset">
|
||||||
|
<legend class="fieldset-legend">Have any coupon ?</legend>
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<input placeholder="Enter coupon here" type="text" class="input" />
|
||||||
|
<button class="btn btn-ghost px-4">Apply</button>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
@if (addressIdControl.invalid && addressIdControl.touched) {
|
||||||
|
<div class="text-red-500 text-sm p-4 mt-4 rounded-xl bg-red-50">
|
||||||
|
Please select an address
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<button
|
||||||
|
class="btn btn-primary w-full mt-4"
|
||||||
|
(click)="proceedToPayment()"
|
||||||
|
[disabled]="addressIdControl.invalid && addressIdControl.touched"
|
||||||
|
>
|
||||||
|
Proceed to payment
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Component, inject, OnInit, signal } from "@angular/core";
|
import { Component, DestroyRef, inject, OnInit, signal } from "@angular/core";
|
||||||
import { AddressForm } from "../components/address-form/address-form";
|
import { AddressForm } from "../components/address-form/address-form";
|
||||||
import { GoBack } from "@app/shared/components/go-back/go-back";
|
import { GoBack } from "@app/shared/components/go-back/go-back";
|
||||||
import { AddressSelect } from "../components/address-select/address-select";
|
import { AddressSelect } from "../components/address-select/address-select";
|
||||||
@ -10,19 +10,27 @@ import {
|
|||||||
} from "@app/features/checkout/services/address-service";
|
} from "@app/features/checkout/services/address-service";
|
||||||
import { AuthService } from "@core/services/auth-service";
|
import { AuthService } from "@core/services/auth-service";
|
||||||
import { User } from "@core/models/user.model";
|
import { User } from "@core/models/user.model";
|
||||||
import { switchMap } from "rxjs";
|
import { of, switchMap } from "rxjs";
|
||||||
|
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||||
|
import { FormControl, ReactiveFormsModule, Validators } from "@angular/forms";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-address",
|
selector: "app-address",
|
||||||
imports: [AddressSelect, AddressForm, GoBack, OrderSummery],
|
imports: [AddressSelect, AddressForm, GoBack, OrderSummery, ReactiveFormsModule],
|
||||||
templateUrl: "./address.html",
|
templateUrl: "./address.html",
|
||||||
styleUrl: "./address.css",
|
styleUrl: "./address.css",
|
||||||
})
|
})
|
||||||
export class Address implements OnInit {
|
export class Address implements OnInit {
|
||||||
addressService = inject(AddressService);
|
addressService = inject(AddressService);
|
||||||
authService = inject(AuthService);
|
authService = inject(AuthService);
|
||||||
private user: User | undefined;
|
|
||||||
|
// I am subscribing to the observable instead of using toSignal(),
|
||||||
|
// i have to destroy the subscription manually.
|
||||||
|
destroyRef = inject(DestroyRef);
|
||||||
|
|
||||||
protected addresses = signal<AddressResponse[]>([]);
|
protected addresses = signal<AddressResponse[]>([]);
|
||||||
|
protected addressIdControl = new FormControl<number | null>(null, Validators.required);
|
||||||
|
private user: User | undefined;
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.authService
|
this.authService
|
||||||
@ -33,8 +41,9 @@ export class Address implements OnInit {
|
|||||||
if (user?.id) {
|
if (user?.id) {
|
||||||
return this.addressService.fetchAddresses(user.id);
|
return this.addressService.fetchAddresses(user.id);
|
||||||
}
|
}
|
||||||
return [];
|
return of({ data: [] });
|
||||||
}),
|
}),
|
||||||
|
takeUntilDestroyed(this.destroyRef),
|
||||||
)
|
)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: (addresses) => {
|
next: (addresses) => {
|
||||||
@ -43,12 +52,12 @@ export class Address implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
createNewAddress(addressData: AddressRequest) {
|
protected createNewAddress(addressData: AddressRequest) {
|
||||||
this.addressService.createAddress(this.user!.id, addressData).subscribe({
|
this.addressService.createAddress(this.user!.id, addressData).subscribe({
|
||||||
next: (address) => this.addresses.update((addresses) => [...addresses, address]),
|
next: (address) => this.addresses.update((addresses) => [...addresses, address]),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
updateAddress(addressData: AddressResponse) {
|
protected updateAddress(addressData: AddressResponse) {
|
||||||
console.log(addressData);
|
console.log(addressData);
|
||||||
this.addressService.updateAddress(addressData.id, addressData).subscribe({
|
this.addressService.updateAddress(addressData.id, addressData).subscribe({
|
||||||
next: (address) =>
|
next: (address) =>
|
||||||
@ -57,4 +66,11 @@ export class Address implements OnInit {
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected proceedToPayment() {
|
||||||
|
if (this.addressIdControl.invalid) {
|
||||||
|
this.addressIdControl.markAsTouched();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,8 @@
|
|||||||
<details class="card p-0!" title="Click to add a new address">
|
<details
|
||||||
|
class="card p-0!"
|
||||||
|
title="Click to add a new address"
|
||||||
|
[open]="isEditing()"
|
||||||
|
>
|
||||||
<summary class="p-6">
|
<summary class="p-6">
|
||||||
<label for="currentAddress" class="font-medium text-gray-600 ml-2"
|
<label for="currentAddress" class="font-medium text-gray-600 ml-2"
|
||||||
>{{isEditing() ? 'Update address' : 'Add new address'}}</label
|
>{{isEditing() ? 'Update address' : 'Add new address'}}</label
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
@if (!isEditing()) {
|
@if (!isEditing()) {
|
||||||
<div class="flex justify-between card">
|
<div class="flex justify-between card">
|
||||||
<div class="flex space-x-4 items-center">
|
<div class="flex space-x-4 items-center">
|
||||||
<input type="radio" name="address" />
|
|
||||||
<p class="text-gray-600 font-medium">{{[address.firstName, address.lastName] | fullname}}</p>
|
<p class="text-gray-600 font-medium">{{[address.firstName, address.lastName] | fullname}}</p>
|
||||||
<p class="text-gray-400 text-sm">
|
<p class="text-gray-400 text-sm">
|
||||||
{{`${address.street}, ${address.city}, ${address.pinCode}`}}
|
{{`${address.street}, ${address.city}, ${address.pinCode}`}}
|
||||||
|
|||||||
@ -1,3 +1,24 @@
|
|||||||
<div class="card h-155">
|
<div class="card">
|
||||||
<p class="text-gray-600 font-medium">Order Summery</p>
|
<p class="text-gray-800 font-medium text-xl">Order Summery</p>
|
||||||
|
@if (cartItems | async; as cart) { @for (item of cart.items; track item.id) {
|
||||||
|
<article
|
||||||
|
class="mt-4 pb-4 border-b border-b-gray-400 border-dashed flex justify-between items-center"
|
||||||
|
>
|
||||||
|
<div class="flex space-x-4">
|
||||||
|
<div class="w-15 h-15 rounded-lg aspect-square relative overflow-hidden">
|
||||||
|
<img ngSrc="{{item.image}}" fill class="object-cover" alt="product image" />
|
||||||
|
</div>
|
||||||
|
<article>
|
||||||
|
<h2>{{item.title}}</h2>
|
||||||
|
<p class="text-gray-600 text-sm">Rs. {{item.price}} x {{item.quantity}}</p>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
<p class="text-gray-800 font-medium">Rs. {{item.subtotal}}</p>
|
||||||
|
</article>
|
||||||
|
}
|
||||||
|
<article class="mt-4 flex justify-between items-center text-lg">
|
||||||
|
<p class="text-gray-800 font-medium">Total</p>
|
||||||
|
<p class="text-gray-800 font-medium">Rs. {{cart.totalPrice}}</p>
|
||||||
|
</article>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,9 +1,19 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component, inject, OnInit } from "@angular/core";
|
||||||
|
import { CartService } from "@core/services/cart-service";
|
||||||
|
import { CartModel } from "@core/models/cart.model";
|
||||||
|
import { Observable } from "rxjs";
|
||||||
|
import { AsyncPipe, NgOptimizedImage } from "@angular/common";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-order-summery",
|
selector: "app-order-summery",
|
||||||
imports: [],
|
imports: [AsyncPipe, NgOptimizedImage],
|
||||||
templateUrl: "./order-summery.html",
|
templateUrl: "./order-summery.html",
|
||||||
styleUrl: "./order-summery.css",
|
styleUrl: "./order-summery.css",
|
||||||
})
|
})
|
||||||
export class OrderSummery {}
|
export class OrderSummery implements OnInit {
|
||||||
|
cartService = inject(CartService);
|
||||||
|
cartItems: Observable<CartModel> | undefined;
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.cartItems = this.cartService.cartItems$;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user