very first commit
This commit is contained in:
258
src/app/pages/cart/cart.component.html
Normal file
258
src/app/pages/cart/cart.component.html
Normal file
@@ -0,0 +1,258 @@
|
||||
<div [class]="isnovo ? 'cart-container novo' : 'cart-container dexar'">
|
||||
<div class="cart-header">
|
||||
<h1>Корзина</h1>
|
||||
@if (itemCount() > 0) {
|
||||
<button class="clear-cart-btn" (click)="clearCart()">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/>
|
||||
</svg>
|
||||
Очистить
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (itemCount() === 0) {
|
||||
<div class="empty-cart">
|
||||
<div class="empty-icon">
|
||||
<app-empty-cart-icon />
|
||||
</div>
|
||||
<h2>Корзина пуста</h2>
|
||||
<p>Добавьте товары, чтобы начать покупки</p>
|
||||
<a routerLink="/" class="shop-btn">Перейти к покупкам</a>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (itemCount() > 0) {
|
||||
<div class="cart-content">
|
||||
<div class="cart-items">
|
||||
@for (item of items(); track trackByItemId($index, item)) {
|
||||
<div class="cart-item-wrapper"
|
||||
[class.swiped]="swipedItemId() === item.itemID"
|
||||
(touchstart)="onSwipeStart(item.itemID, $event)">
|
||||
<div class="cart-item">
|
||||
<a [routerLink]="['/item', item.itemID]" class="item-image">
|
||||
<img [src]="getMainImage(item)" [alt]="item.name" loading="lazy" />
|
||||
</a>
|
||||
|
||||
<div class="item-info">
|
||||
<div class="item-header">
|
||||
<a [routerLink]="['/item', item.itemID]" class="item-name">{{ item.name }}</a>
|
||||
<button class="remove-btn" (click)="removeItem(item.itemID)" title="Remove">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M18 6L6 18M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p class="item-description">{{ item.description.substring(0, 100) }}...</p>
|
||||
|
||||
<div class="item-footer">
|
||||
<div class="item-pricing">
|
||||
@if (item.discount > 0) {
|
||||
<div class="price-with-discount">
|
||||
<span class="original-price">{{ item.price }} ₽</span>
|
||||
<span class="current-price">{{ getDiscountedPrice(item) | number:'1.2-2' }} ₽</span>
|
||||
</div>
|
||||
} @else {
|
||||
<span class="current-price">{{ item.price }} ₽</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="quantity-controls">
|
||||
<button class="qty-btn" (click)="decreaseQuantity(item.itemID, item.quantity)" [disabled]="item.quantity <= 1">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
||||
<path d="M5 12h14"/>
|
||||
</svg>
|
||||
</button>
|
||||
<span class="qty-value">{{ item.quantity }}</span>
|
||||
<button class="qty-btn" (click)="increaseQuantity(item.itemID, item.quantity)">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
||||
<path d="M12 5v14M5 12h14"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="delete-btn-mobile" (click)="removeItem(item.itemID)">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="cart-summary">
|
||||
<div class="summary-header">
|
||||
<h3>Итого</h3>
|
||||
</div>
|
||||
|
||||
<div class="summary-row">
|
||||
<span>Товары ({{ itemCount() }})</span>
|
||||
<span class="value">{{ totalPrice() | number:'1.2-2' }} ₽</span>
|
||||
</div>
|
||||
|
||||
<div class="summary-row delivery">
|
||||
<span>Доставка</span>
|
||||
<span>0 ₽</span>
|
||||
</div>
|
||||
|
||||
<div class="summary-row total">
|
||||
<span>К оплате</span>
|
||||
<span class="total-price">{{ totalPrice() | number:'1.2-2' }} ₽</span>
|
||||
</div>
|
||||
|
||||
<div class="terms-agreement">
|
||||
<label class="checkbox-container">
|
||||
<input
|
||||
type="checkbox"
|
||||
[(ngModel)]="termsAccepted"
|
||||
id="terms-checkbox"
|
||||
/>
|
||||
<span class="checkmark"></span>
|
||||
<span class="terms-text">
|
||||
Я согласен с
|
||||
<a routerLink="/public-offer" target="_blank">публичной офертой</a>,
|
||||
<a routerLink="/return-policy" target="_blank">политикой возврата</a>,
|
||||
<a routerLink="/guarantee" target="_blank">условиями гарантии</a> и
|
||||
<a routerLink="/privacy-policy" target="_blank">политикой конфиденциальности</a>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="checkout-btn"
|
||||
(click)="checkout()"
|
||||
[class.disabled]="!termsAccepted"
|
||||
[disabled]="!termsAccepted"
|
||||
>
|
||||
Оформить заказ
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Payment Popup Modal -->
|
||||
@if (showPaymentPopup()) {
|
||||
<div class="payment-modal-overlay">
|
||||
<div class="payment-modal">
|
||||
<button class="close-modal-btn" (click)="closePaymentPopup()" aria-label="Закрыть">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M6 6L18 18M6 18L18 6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
@if (paymentStatus() === 'creating') {
|
||||
<div class="payment-status-screen">
|
||||
<div class="spinner-large"></div>
|
||||
<h2>Создание платежа...</h2>
|
||||
<p>Подождите несколько секунд</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (paymentStatus() === 'waiting') {
|
||||
<div class="payment-active">
|
||||
<h2>Сканируйте QR-код для оплаты</h2>
|
||||
|
||||
<div class="qr-section">
|
||||
<div class="qr-wrapper">
|
||||
<img [src]="qrCodeUrl()" alt="QR код для оплаты" class="qr-code" />
|
||||
<div class="scan-line"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="payment-info">
|
||||
<div class="payment-amount">
|
||||
<span class="label">Сумма к оплате:</span>
|
||||
<span class="amount">{{ totalPrice() | number:'1.2-2' }} RUB</span>
|
||||
</div>
|
||||
|
||||
<div class="waiting-indicator">
|
||||
<div class="pulse-dot"></div>
|
||||
<span>Ожидание оплаты...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="payment-actions">
|
||||
<button class="copy-btn" (click)="copyPaymentLink()">
|
||||
{{ linkCopied() ? '✓ Скопировано' : 'Скопировать ссылку' }}
|
||||
</button>
|
||||
<a [href]="paymentUrl()" target="_blank" rel="noopener noreferrer" class="open-btn">
|
||||
Открыть в новой вкладке
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (paymentStatus() === 'success') {
|
||||
<div class="payment-status-screen success">
|
||||
<div class="success-icon">✓</div>
|
||||
<h2>Поздравляем! Оплата прошла успешно!</h2>
|
||||
<p class="success-text">Введите ваши контактные данные, и мы отправим вам покупку в течение нескольких минут</p>
|
||||
|
||||
<div class="email-form">
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="email"
|
||||
class="email-input"
|
||||
[class.valid]="emailTouched() && !emailError()"
|
||||
[class.invalid]="emailTouched() && emailError()"
|
||||
placeholder="your@email.com"
|
||||
[value]="userEmail()"
|
||||
(input)="onEmailInput($event)"
|
||||
(blur)="onEmailBlur()"
|
||||
[disabled]="emailSubmitting()"
|
||||
maxlength="100"
|
||||
/>
|
||||
@if (emailTouched() && emailError()) {
|
||||
<div class="error-message">{{ emailError() }}</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="tel"
|
||||
class="email-input phone-input"
|
||||
[class.valid]="phoneTouched() && !phoneError()"
|
||||
[class.invalid]="phoneTouched() && phoneError()"
|
||||
placeholder="+7 (900) 123-45-67"
|
||||
[value]="userPhone()"
|
||||
(input)="onPhoneInput($event)"
|
||||
(blur)="onPhoneBlur()"
|
||||
[disabled]="emailSubmitting()"
|
||||
(keyup.enter)="submitEmail()"
|
||||
/>
|
||||
@if (phoneTouched() && phoneError()) {
|
||||
<div class="error-message">{{ phoneError() }}</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="submit-email-btn"
|
||||
(click)="submitEmail()"
|
||||
[disabled]="emailSubmitting()"
|
||||
>
|
||||
@if (emailSubmitting()) {
|
||||
<span class="spinner-small"></span>
|
||||
Отправка...
|
||||
} @else {
|
||||
Отправить
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (paymentStatus() === 'timeout') {
|
||||
<div class="payment-status-screen timeout">
|
||||
<div class="timeout-icon">⏱</div>
|
||||
<h2>Время ожидания истекло</h2>
|
||||
<p>Мы не получили подтверждение оплаты в течение 3 минут.</p>
|
||||
<p class="auto-close">Окно закроется автоматически...</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
Reference in New Issue
Block a user