Überarbeitung des Stripe Prozesses
This commit is contained in:
@@ -7,15 +7,22 @@ import { LoadingService } from '../services/loading.service';
|
||||
@Injectable()
|
||||
export class LoadingInterceptor implements HttpInterceptor {
|
||||
constructor(private loadingService: LoadingService) {}
|
||||
|
||||
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
|
||||
const hideLoading = request.headers.get('X-Hide-Loading') === 'true';
|
||||
const requestId = `HTTP-${v4()}`;
|
||||
this.loadingService.startLoading(requestId, request.url);
|
||||
|
||||
if (!hideLoading) {
|
||||
this.loadingService.startLoading(requestId, request.url);
|
||||
}
|
||||
|
||||
return next.handle(request).pipe(
|
||||
tap({
|
||||
finalize: () => this.loadingService.stopLoading(requestId), // Stoppt den Ladevorgang, wenn die Anfrage abgeschlossen ist
|
||||
// Beachte, dass 'error' und 'complete' hier entfernt wurden, da 'finalize' in allen Fällen aufgerufen wird,
|
||||
// egal ob die Anfrage erfolgreich war, einen Fehler geworfen hat oder abgeschlossen wurde.
|
||||
finalize: () => {
|
||||
if (!hideLoading) {
|
||||
this.loadingService.stopLoading(requestId);
|
||||
}
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
@if(user){
|
||||
<a routerLink="/account" class="text-blue-600 border border-blue-600 px-3 py-2 rounded">Account</a>
|
||||
} @else {
|
||||
<a routerLink="/pricing" class="text-gray-800">Pricing</a>
|
||||
<!-- <a routerLink="/pricing" class="text-gray-800">Pricing</a> -->
|
||||
<a (click)="login()" class="text-blue-600 border border-blue-600 px-3 py-2 rounded">Log In</a>
|
||||
<a routerLink="/pricing" class="text-white bg-blue-600 px-4 py-2 rounded">Register</a>
|
||||
}
|
||||
|
||||
@@ -43,7 +43,9 @@ export class PricingComponent {
|
||||
}
|
||||
} else {
|
||||
if (priceId) {
|
||||
this.keycloakService.register({ redirectUri: `${window.location.origin}/pricing/${btoa(priceId)}` });
|
||||
this.keycloakService.register({
|
||||
redirectUri: `${window.location.origin}/pricing/${btoa(priceId)}`,
|
||||
});
|
||||
} else {
|
||||
this.keycloakService.register({ redirectUri: `${window.location.origin}/account` });
|
||||
}
|
||||
|
||||
@@ -243,9 +243,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-start">
|
||||
<button routerLink="/pricing" class="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">Upgrade Subscription Plan</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 sm:hidden">
|
||||
<h3 class="text-lg font-medium text-gray-700 mb-1">Membership Level</h3>
|
||||
<div class="space-y-2">
|
||||
@@ -279,6 +277,16 @@
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@if(user.subscriptionPlan==='free'){
|
||||
<div class="flex justify-start">
|
||||
<button
|
||||
routerLink="/pricing"
|
||||
class="py-2.5 px-5 me-2 mb-2 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"
|
||||
>
|
||||
Upgrade Subscription Plan
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DatePipe, TitleCasePipe } from '@angular/common';
|
||||
import { ChangeDetectorRef, Component } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { faTrash } from '@fortawesome/free-solid-svg-icons';
|
||||
import { NgSelectModule } from '@ng-select/ng-select';
|
||||
import { initFlowbite } from 'flowbite';
|
||||
@@ -32,7 +32,7 @@ import { SharedService } from '../../../services/shared.service';
|
||||
import { SubscriptionsService } from '../../../services/subscriptions.service';
|
||||
import { UserService } from '../../../services/user.service';
|
||||
import { SharedModule } from '../../../shared/shared/shared.module';
|
||||
import { map2User } from '../../../utils/utils';
|
||||
import { checkAndUpdate, map2User } from '../../../utils/utils';
|
||||
import { TOOLBAR_OPTIONS } from '../../utils/defaults';
|
||||
@Component({
|
||||
selector: 'app-account',
|
||||
@@ -93,6 +93,7 @@ export class AccountComponent {
|
||||
private validationMessagesService: ValidationMessagesService,
|
||||
private subscriptionService: SubscriptionsService,
|
||||
private datePipe: DatePipe,
|
||||
private router: Router,
|
||||
) {}
|
||||
async ngOnInit() {
|
||||
setTimeout(() => {
|
||||
@@ -108,9 +109,11 @@ export class AccountComponent {
|
||||
}
|
||||
|
||||
this.subscriptions = await lastValueFrom(this.subscriptionService.getAllSubscriptions(this.user.email));
|
||||
if (this.subscriptions.length === 0) {
|
||||
this.subscriptions = [{ ended_at: null, start_date: Math.floor(new Date(this.user.created).getTime() / 1000), status: null, metadata: { plan: 'Free Plan' } }];
|
||||
}
|
||||
await this.synchronizeSubscriptions(this.subscriptions);
|
||||
// if (this.subscriptions.length === 0) {
|
||||
// this.subscriptions = [{ ended_at: null, start_date: Math.floor(new Date(this.user.created).getTime() / 1000), status: null, metadata: { plan: 'Free Plan' } }];
|
||||
// }
|
||||
|
||||
this.profileUrl = this.user.hasProfile ? `${this.env.imageBaseUrl}/pictures/profile/${emailToDirName(this.user.email)}.avif?_ts=${new Date().getTime()}` : `/assets/images/placeholder.png`;
|
||||
this.companyLogoUrl = this.user.hasCompanyLogo ? `${this.env.imageBaseUrl}/pictures/logo/${emailToDirName(this.user.email)}.avif?_ts=${new Date().getTime()}` : `/assets/images/placeholder.png`;
|
||||
|
||||
@@ -128,6 +131,36 @@ export class AccountComponent {
|
||||
label: this.titleCasePipe.transform(type.name),
|
||||
}));
|
||||
}
|
||||
async synchronizeSubscriptions(subscriptions: StripeSubscription[]) {
|
||||
let changed = false;
|
||||
if (this.subscriptions.length === 0) {
|
||||
if (!this.user.subscriptionPlan) {
|
||||
this.router.navigate(['pricing']);
|
||||
} else {
|
||||
this.subscriptions = [{ ended_at: null, start_date: Math.floor(new Date(this.user.created).getTime() / 1000), status: null, metadata: { plan: 'Free Plan' } }];
|
||||
changed = checkAndUpdate(changed, this.user.customerType !== 'buyer' && this.user.customerType !== 'seller', () => (this.user.customerType = 'buyer'));
|
||||
changed = checkAndUpdate(changed, !!this.user.customerSubType, () => (this.user.customerSubType = null));
|
||||
changed = checkAndUpdate(changed, this.user.subscriptionPlan !== 'free', () => (this.user.subscriptionPlan = 'free'));
|
||||
changed = checkAndUpdate(changed, !!this.user.subscriptionId, () => (this.user.subscriptionId = null));
|
||||
}
|
||||
} else {
|
||||
const subscription = subscriptions[0];
|
||||
changed = checkAndUpdate(changed, subscription.metadata['plan'] === 'Broker Plan' && this.user.customerType !== 'professional', () => (this.user.customerType = 'professional'));
|
||||
changed = checkAndUpdate(changed, subscription.metadata['plan'] === 'Broker Plan' && this.user.customerSubType !== 'broker', () => (this.user.customerSubType = 'broker'));
|
||||
changed = checkAndUpdate(changed, subscription.metadata['plan'] === 'Broker Plan' && this.user.subscriptionPlan !== 'broker', () => (this.user.subscriptionPlan = 'broker'));
|
||||
changed = checkAndUpdate(changed, subscription.metadata['plan'] === 'Broker Plan' && !this.user.subscriptionId, () => (this.user.subscriptionId = subscription.id));
|
||||
|
||||
changed = checkAndUpdate(changed, subscription.metadata['plan'] === 'Professional Plan' && this.user.customerType !== 'professional', () => (this.user.customerType = 'professional'));
|
||||
changed = checkAndUpdate(changed, subscription.metadata['plan'] === 'Professional Plan' && this.user.subscriptionPlan !== 'professional', () => (this.user.subscriptionPlan = 'professional'));
|
||||
changed = checkAndUpdate(changed, subscription.metadata['plan'] === 'Professional Plan' && this.user.subscriptionId !== 'professional', () => (this.user.subscriptionId = subscription.id));
|
||||
}
|
||||
if (changed) {
|
||||
await this.userService.saveGuaranteed(this.user);
|
||||
this.cdref.detectChanges();
|
||||
this.cdref.markForCheck();
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.validationMessagesService.clearMessages(); // Löschen Sie alle bestehenden Validierungsnachrichten
|
||||
}
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
<div class="min-h-screen flex items-center justify-center">
|
||||
<div class="bg-white p-6 rounded-lg shadow-lg max-w-md">
|
||||
<div class="text-center">
|
||||
@if(user && (user.subscriptionPlan==='professional' || user.subscriptionPlan==='broker')){
|
||||
<!-- Neue Bedingung hinzufügen -->
|
||||
@if(maxAttemptsReached) {
|
||||
<h2 class="text-2xl font-bold text-red-800 mt-4">We're sorry!</h2>
|
||||
<p class="text-gray-600 mt-2">
|
||||
We regret to inform you that we have not yet received any response from our payment service provider regarding the status of your subscription. Please log in to the
|
||||
<a href="https://www.bizmatch.net" class="text-blue-500 hover:underline">website</a> and check your subscription status under the Account menu. If you have any questions, please contact us at
|
||||
<a href="mailto:support@bizmatch.net" class="text-blue-500 hover:underline">support@bizmatch.net</a>.
|
||||
</p>
|
||||
} @else if(user && (user.subscriptionPlan==='professional' || user.subscriptionPlan==='broker')) {
|
||||
<svg class="mx-auto h-16 w-16 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
|
||||
</svg>
|
||||
|
||||
@@ -16,7 +16,10 @@ import { map2User } from '../../utils/utils';
|
||||
})
|
||||
export class SuccessComponent {
|
||||
user: User;
|
||||
maxAttemptsReached: boolean = false; // Neue Variable hinzufügen
|
||||
|
||||
constructor(private keycloakService: KeycloakService, private userService: UserService, private logService: LogService, private router: Router) {}
|
||||
|
||||
async ngOnInit() {
|
||||
let email = null;
|
||||
try {
|
||||
@@ -29,6 +32,7 @@ export class SuccessComponent {
|
||||
this.checkSubscriptionPlan(email, e.message);
|
||||
}
|
||||
}
|
||||
|
||||
async checkSubscriptionPlan(email: string, error?: string) {
|
||||
if (!email) {
|
||||
this.logService.log({ severity: 'error', text: `Unauthorized Access to Success Page ${error}` });
|
||||
@@ -44,12 +48,13 @@ export class SuccessComponent {
|
||||
if (attempts >= maxAttempts) {
|
||||
clearInterval(intervalId);
|
||||
console.error('Max attempts reached');
|
||||
this.maxAttemptsReached = true; // Setze die Variable auf true, wenn die max. Versuche erreicht wurden
|
||||
return;
|
||||
}
|
||||
|
||||
attempts++;
|
||||
|
||||
this.user = await this.userService.getByMail(email);
|
||||
this.user = await this.userService.getByMail(email, true);
|
||||
|
||||
if (this.user && this.user.subscriptionPlan) {
|
||||
clearInterval(intervalId);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { lastValueFrom, Observable } from 'rxjs';
|
||||
import urlcat from 'urlcat';
|
||||
@@ -20,12 +20,19 @@ export class UserService {
|
||||
async save(user: User): Promise<User> {
|
||||
return await lastValueFrom(this.http.post<User>(`${this.apiBaseUrl}/bizmatch/user`, user));
|
||||
}
|
||||
async saveGuaranteed(user: User): Promise<User> {
|
||||
return await lastValueFrom(this.http.post<User>(`${this.apiBaseUrl}/bizmatch/user/guaranteed`, user));
|
||||
}
|
||||
async getById(id: string): Promise<User> {
|
||||
return await lastValueFrom(this.http.get<User>(`${this.apiBaseUrl}/bizmatch/user/${id}`));
|
||||
}
|
||||
async getByMail(mail: string): Promise<User> {
|
||||
async getByMail(mail: string, hideLoading: boolean = true): Promise<User> {
|
||||
const url = urlcat(`${this.apiBaseUrl}/bizmatch/user`, { mail });
|
||||
return await lastValueFrom(this.http.get<User>(url));
|
||||
let headers = new HttpHeaders();
|
||||
if (hideLoading) {
|
||||
headers = headers.set('X-Hide-Loading', 'true');
|
||||
}
|
||||
return await lastValueFrom(this.http.get<User>(url, { headers }));
|
||||
}
|
||||
async search(criteria?: UserListingCriteria): Promise<ResponseUsersArray> {
|
||||
return await lastValueFrom(this.http.post<ResponseUsersArray>(`${this.apiBaseUrl}/bizmatch/user/search`, criteria));
|
||||
|
||||
@@ -287,6 +287,12 @@ export function assignProperties(target, source) {
|
||||
}
|
||||
return target;
|
||||
}
|
||||
export function checkAndUpdate(changed: boolean, condition: boolean, assignment: () => any): boolean {
|
||||
if (condition) {
|
||||
assignment();
|
||||
}
|
||||
return changed || condition;
|
||||
}
|
||||
// -----------------------------
|
||||
// Criteria Proxy
|
||||
// -----------------------------
|
||||
|
||||
Reference in New Issue
Block a user