feat: client-side currency conversion with admin-configurable rates
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
- CurrencyRatesService: RUB-based rates, persisted via localStorage - CurrencyConvertPipe: impure pipe converting item price to selected currency - Admin settings page: editable currency rates form - Applied conversion to product-card, product-information, quick-view-dialog, delivery-information, compare-table, cart totals + payment payload Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -22,12 +22,14 @@ import { TenantResolverService } from '../../core/config/tenant-resolver.service
|
||||
import { UserNotificationService } from '../../features/website/user-experience/services/user-notification.service';
|
||||
import { ConfirmDialogComponent } from '../../shared/ui/confirm-dialog/confirm-dialog.component';
|
||||
import { DialogComponent } from '../../shared/ui/dialog/dialog.component';
|
||||
import { CurrencyConvertPipe } from '../../pipes/currency-convert.pipe';
|
||||
import { CurrencyRatesService } from '../../services/currency-rates.service';
|
||||
|
||||
type PaymentMethod = 'qr' | 'card';
|
||||
|
||||
@Component({
|
||||
selector: 'app-cart',
|
||||
imports: [DecimalPipe, RouterLink, FormsModule, DeliverySelectorComponent, TelegramLoginComponent, LangRoutePipe, TranslatePipe, IconComponent, EmptyStateComponent, ButtonComponent, ConfirmDialogComponent, DialogComponent],
|
||||
imports: [DecimalPipe, RouterLink, FormsModule, DeliverySelectorComponent, TelegramLoginComponent, LangRoutePipe, TranslatePipe, IconComponent, EmptyStateComponent, ButtonComponent, ConfirmDialogComponent, DialogComponent, CurrencyConvertPipe],
|
||||
templateUrl: './cart.component.html',
|
||||
styleUrls: ['./cart.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
@@ -80,6 +82,7 @@ export class CartComponent implements OnDestroy {
|
||||
|
||||
private configService = inject(ConfigService);
|
||||
private tenantResolver = inject(TenantResolverService);
|
||||
private currencyRates = inject(CurrencyRatesService);
|
||||
|
||||
constructor(
|
||||
private cartService: CartService,
|
||||
@@ -183,6 +186,10 @@ export class CartComponent implements OnDestroy {
|
||||
itemName(item: Item): string { return getTranslatedField(item, 'name', this.langService.currentLanguage()); }
|
||||
itemDesc(item: Item): string { return getTranslatedField(item, 'simpleDescription', this.langService.currentLanguage()); }
|
||||
get currentCurrency(): string { return this.langService.currentCurrency(); }
|
||||
/** Cart totals are summed in the base currency (RUB); convert to whatever the shopper has selected. */
|
||||
convertTotal(amountInBaseCurrency: number): number {
|
||||
return this.currencyRates.convert(amountInBaseCurrency, this.currencyRates.baseCurrency, this.currentCurrency);
|
||||
}
|
||||
get isCheckoutDisabled(): boolean { return !this.termsAccepted || !this.isAuthenticated() || !this.allRequiredDeliveriesSelected(); }
|
||||
|
||||
selectDelivery(itemID: number, selectedDelivery: DeliveryOption | null): void {
|
||||
@@ -255,7 +262,7 @@ export class CartComponent implements OnDestroy {
|
||||
createPayment(paymentMethod: PaymentMethod): void {
|
||||
const orderId = this.generateOrderId();
|
||||
const paymentPayload = {
|
||||
amount: Number(this.totalWithDelivery()),
|
||||
amount: Number(this.convertTotal(this.totalWithDelivery())),
|
||||
currency: this.langService.currentCurrency(),
|
||||
siteuserID: this.getPaymentUserId(),
|
||||
siteorderID: orderId,
|
||||
|
||||
Reference in New Issue
Block a user