feature: implement payment verification, make cart as converted after successful payment
This commit is contained in:
parent
85b0fbf499
commit
aa35fe44b3
@ -6,10 +6,11 @@ import { Cart } from "@app/shared/components/cart/cart";
|
||||
import { CartModel } from "@app/core/models/cart.model";
|
||||
import { map } from "rxjs";
|
||||
import { AsyncPipe } from "@angular/common";
|
||||
import { RouterLink } from "@angular/router";
|
||||
|
||||
@Component({
|
||||
selector: "app-header",
|
||||
imports: [LucideAngularModule, Cart, AsyncPipe],
|
||||
imports: [LucideAngularModule, Cart, AsyncPipe, RouterLink],
|
||||
templateUrl: "./header.html",
|
||||
styleUrl: "./header.css",
|
||||
})
|
||||
@ -19,8 +20,7 @@ export class Header {
|
||||
readonly SearchIcon = Search;
|
||||
readonly authService = inject(AuthService);
|
||||
readonly cartService = inject(CartService);
|
||||
protected readonly AuthState = AuthState;
|
||||
|
||||
cartItems$ = this.cartService.cartItems$;
|
||||
cartItemCount = this.cartItems$.pipe(map((cart: CartModel) => cart.itemsCount ?? 0));
|
||||
protected readonly AuthState = AuthState;
|
||||
}
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
|
||||
import { effect, inject, Injectable, signal } from "@angular/core";
|
||||
import { effect, inject, Injectable } from "@angular/core";
|
||||
import { API_URL } from "../tokens/api-url-tokens";
|
||||
import { CartItemModel, CartItemRequest, CartModel } from "../models/cart.model";
|
||||
import { AuthService, AuthState } from "@core/services/auth-service";
|
||||
import { Cart } from "@app/shared/components/cart/cart";
|
||||
import { CartItemRequest, CartModel } from "../models/cart.model";
|
||||
import { AuthService } from "@core/services/auth-service";
|
||||
import { BehaviorSubject, tap } from "rxjs";
|
||||
|
||||
@Injectable({
|
||||
@ -29,7 +28,7 @@ export class CartService {
|
||||
});
|
||||
}
|
||||
|
||||
private fetchCart() {
|
||||
fetchCart() {
|
||||
return this.http.get<CartModel>(this.apiUrl + "/cart").subscribe({
|
||||
next: (data) => this._cartItems.next(data),
|
||||
error: (error: HttpErrorResponse) => {
|
||||
|
||||
@ -1,27 +1,47 @@
|
||||
<div class="flex flex-col gap-4 items-center justify-center">
|
||||
<app-loading-spinner [isLoading]="isProcessing()">
|
||||
<div class="card max-w-md text-center flex items-center flex-col gap-4">
|
||||
<div class="rounded-full bg-green-100 p-4">
|
||||
<div
|
||||
[class.bg-green-100]="paymentData()!.isSuccess"
|
||||
[class.bg-red-100]="!paymentData()!.isSuccess"
|
||||
class="rounded-full p-4"
|
||||
>
|
||||
@if (paymentData()!.isSuccess) {
|
||||
<lucide-angular [img]="BadgeCheck" class="w-6 h-6 text-green-500" />
|
||||
} @else {
|
||||
<lucide-angular [img]="BadgeQuestionMark" class="w-6 h-6 text-red-500" />
|
||||
}
|
||||
</div>
|
||||
<p class="text-xl font-medium text-green-600">Payment Successful</p>
|
||||
<p class="text-sm text-gray-400">
|
||||
Your payment processed successfully. You will receive a confirmation email shortly.
|
||||
<p
|
||||
[class.text-green-500]="paymentData()!.isSuccess"
|
||||
[class.text-red-500]="!paymentData()!.isSuccess"
|
||||
class="text-xl font-medium"
|
||||
>
|
||||
{{ paymentData()!.message }}
|
||||
</p>
|
||||
<p class="text-sm text-gray-400">
|
||||
@if (paymentData()!.isSuccess) { Your payment processed successfully. You will receive a
|
||||
confirmation email shortly. } @else { If money is debited then wait for few hours then check
|
||||
payment status. }
|
||||
</p>
|
||||
@if (paymentData()!.isSuccess) {
|
||||
<article class="rounded-xl bg-gray-100 px-3 py-4 text-gray-500 text-sm w-full space-y-4">
|
||||
<article class="flex justify-between border-b border-b-gray-200 pb-4">
|
||||
<p class="font-medium">Amount</p>
|
||||
<p>Rs. 20000</p>
|
||||
<p>Rs.{{ paymentData()?.amount }}</p>
|
||||
</article>
|
||||
|
||||
<article class="flex justify-between">
|
||||
<p class="font-medium">Transaction ID</p>
|
||||
<p class="truncate">text_ch_989789y789jhhg8h8</p>
|
||||
<p class="truncate">{{ paymentData()?.transactionId }}</p>
|
||||
</article>
|
||||
<article class="flex justify-between">
|
||||
<p class="font-medium">Payment method</p>
|
||||
<p>Stripe Checkout</p>
|
||||
<p>{{ paymentData()?.paymentMethod | uppercase }}</p>
|
||||
</article>
|
||||
</article>
|
||||
}
|
||||
</div>
|
||||
</app-loading-spinner>
|
||||
<app-go-back class="w-min-content! flex-nowrap" route="/" text="Continue Shopping" />
|
||||
</div>
|
||||
|
||||
@ -1,24 +1,73 @@
|
||||
import { Component, inject } from "@angular/core";
|
||||
import { BadgeCheck, LucideAngularModule } from "lucide-angular";
|
||||
import { Component, DestroyRef, inject, OnInit, signal } from "@angular/core";
|
||||
import { BadgeCheck, BadgeQuestionMark, LucideAngularModule } from "lucide-angular";
|
||||
import { GoBack } from "@shared/components/go-back/go-back";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { LoadingSpinner } from "@shared/components/loading-spinner/loading-spinner";
|
||||
import {
|
||||
OrderService,
|
||||
PaymentVerificationResponse,
|
||||
} from "@app/features/checkout/services/order-service";
|
||||
import { finalize, tap } from "rxjs";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { UpperCasePipe } from "@angular/common";
|
||||
import { CartService } from "@core/services/cart-service";
|
||||
|
||||
@Component({
|
||||
selector: "app-confirmation",
|
||||
imports: [LucideAngularModule, GoBack],
|
||||
imports: [LucideAngularModule, GoBack, LoadingSpinner, UpperCasePipe],
|
||||
templateUrl: "./confirmation.html",
|
||||
styleUrl: "./confirmation.css",
|
||||
})
|
||||
class Confirmation {
|
||||
export default class Confirmation implements OnInit {
|
||||
destroyRef = inject(DestroyRef);
|
||||
protected paymentData = signal<PaymentVerificationResponse | null>(null);
|
||||
protected isProcessing = signal(false);
|
||||
protected readonly BadgeCheck = BadgeCheck;
|
||||
protected readonly BadgeQuestionMark = BadgeQuestionMark;
|
||||
private route = inject(ActivatedRoute);
|
||||
private orderService = inject(OrderService);
|
||||
private cartService = inject(CartService);
|
||||
private orderId: string | null = null;
|
||||
private sessionId: string | null = null;
|
||||
|
||||
ngOnInit() {
|
||||
this.orderId = this.route.snapshot.paramMap.get("order_id");
|
||||
this.sessionId = this.route.snapshot.paramMap.get("session_id");
|
||||
}
|
||||
this.orderId = this.route.snapshot.queryParamMap.get("order_id");
|
||||
this.sessionId = this.route.snapshot.queryParamMap.get("session_id");
|
||||
this.checkConfirmation();
|
||||
}
|
||||
|
||||
export default Confirmation;
|
||||
private checkConfirmation() {
|
||||
if (!this.orderId || !this.sessionId) {
|
||||
console.error("Missing order ID or session ID");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.isProcessing.set(true);
|
||||
const orderId = parseInt(this.orderId!);
|
||||
this.orderService
|
||||
.verifyPayment(orderId, this.sessionId!)
|
||||
.pipe(
|
||||
tap((data) => {
|
||||
this.paymentData.set(data);
|
||||
if (data && data.isSuccess) {
|
||||
this.cartService.fetchCart();
|
||||
}
|
||||
}),
|
||||
finalize(() => this.isProcessing.set(false)),
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
console.log("Payment verified successfully");
|
||||
},
|
||||
error: (err) => {
|
||||
console.error(err);
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
this.isProcessing.set(false);
|
||||
console.error(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,14 @@ import { FormControl, Validators } from "@angular/forms";
|
||||
import { tap } from "rxjs";
|
||||
import { SessionStorageService } from "@core/services/session-storage.service";
|
||||
|
||||
export interface PaymentVerificationResponse {
|
||||
isSuccess: boolean;
|
||||
message: string;
|
||||
amount: number | null;
|
||||
transactionId: string | null;
|
||||
paymentMethod: string | null;
|
||||
}
|
||||
|
||||
export interface CheckoutResponse {
|
||||
success: boolean;
|
||||
amount: number;
|
||||
@ -61,4 +69,11 @@ export class OrderService {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
verifyPayment(orderId: number, sessionId: string) {
|
||||
return this.http.post<PaymentVerificationResponse>(`${this.apiUrl}/payments/verify`, {
|
||||
orderId: orderId,
|
||||
sessionId: sessionId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user