Compare commits
2 Commits
138b774073
...
b4ad6da49e
| Author | SHA1 | Date | |
|---|---|---|---|
| b4ad6da49e | |||
| 679e404dc8 |
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
export interface FastcheckData {
|
export interface FastcheckData {
|
||||||
fastcheck: string;
|
fastcheck: string;
|
||||||
amount: number;
|
amount: number | null;
|
||||||
code: string;
|
code: string;
|
||||||
expiration?: string;
|
expiration?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,16 +122,24 @@
|
|||||||
}
|
}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- QR section: shown after QR is created -->
|
<!-- QR popup overlay -->
|
||||||
@if (qrImageUrl()) {
|
@if (qrImageUrl()) {
|
||||||
<div class="qr-section">
|
<div class="qr-overlay" (click)="closeQr()">
|
||||||
<p class="qr-section__label">{{ 'create.qr_label' | translate }}</p>
|
<div class="qr-modal" (click)="$event.stopPropagation()">
|
||||||
<img class="qr-section__img" [src]="qrImageUrl()!" width="240" height="240" alt="QR" />
|
<button class="qr-modal__close" type="button" (click)="closeQr()" aria-label="Close">
|
||||||
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||||
|
stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M18 6L6 18M6 6l12 12"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<p class="qr-modal__label">{{ 'create.qr_label' | translate }}</p>
|
||||||
|
<img class="qr-modal__img" [src]="qrImageUrl()!" width="260" height="260" alt="QR" />
|
||||||
@if (qrPolling()) {
|
@if (qrPolling()) {
|
||||||
<p class="qr-section__hint">{{ 'create.qr_waiting' | translate }}</p>
|
<p class="qr-modal__hint">{{ 'create.qr_waiting' | translate }}</p>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card__footer">
|
<div class="card__footer">
|
||||||
|
|||||||
@@ -175,12 +175,49 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ─── QR section ─────────────────────────────────────────────────────────────
|
// ─── QR section ─────────────────────────────────────────────────────────────
|
||||||
.qr-section {
|
// ─── QR popup ───────────────────────────────────────────────────────────────
|
||||||
|
.qr-overlay {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.55);
|
||||||
|
z-index: 1000;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
animation: overlay-in 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-modal {
|
||||||
|
position: relative;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 32px 28px 24px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 14px;
|
||||||
padding: 16px 0 8px;
|
box-shadow: 0 20px 60px rgba(0,0,0,0.25);
|
||||||
|
animation: modal-in 0.22s cubic-bezier(.34,1.56,.64,1);
|
||||||
|
max-width: 340px;
|
||||||
|
width: 90vw;
|
||||||
|
|
||||||
|
&__close {
|
||||||
|
position: absolute;
|
||||||
|
top: 12px;
|
||||||
|
right: 12px;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: none;
|
||||||
|
background: #f1f5f9;
|
||||||
|
color: #475569;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: background 0.15s;
|
||||||
|
&:hover { background: #e2e8f0; }
|
||||||
|
}
|
||||||
|
|
||||||
&__label {
|
&__label {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@@ -202,6 +239,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes overlay-in {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes modal-in {
|
||||||
|
from { opacity: 0; transform: scale(0.85); }
|
||||||
|
to { opacity: 1; transform: scale(1); }
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0%, 100% { opacity: 1; }
|
0%, 100% { opacity: 1; }
|
||||||
50% { opacity: 0.45; }
|
50% { opacity: 0.45; }
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export class CreatePage {
|
|||||||
minAmount = signal<number>(30);
|
minAmount = signal<number>(30);
|
||||||
maxAmount = signal<number>(200_000);
|
maxAmount = signal<number>(200_000);
|
||||||
|
|
||||||
amount = signal<number>(100);
|
amount = signal<number | null>(null);
|
||||||
note = signal<string>('');
|
note = signal<string>('');
|
||||||
error = signal<string>('');
|
error = signal<string>('');
|
||||||
loading = signal<boolean>(false);
|
loading = signal<boolean>(false);
|
||||||
@@ -122,11 +122,11 @@ export class CreatePage {
|
|||||||
|
|
||||||
createCheck(): void {
|
createCheck(): void {
|
||||||
const val = this.amount();
|
const val = this.amount();
|
||||||
if (!val || val < this.minAmount()) {
|
if (val !== null && val < this.minAmount()) {
|
||||||
this.error.set(`${this.t('errors.invalid_amount')} (мин. ${this.minAmount()} ₽)`);
|
this.error.set(`${this.t('errors.invalid_amount')} (мин. ${this.minAmount()} ₽)`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (val > this.maxAmount()) {
|
if (val !== null && val > this.maxAmount()) {
|
||||||
this.error.set(`${this.t('errors.invalid_amount')} (макс. ${this.maxAmount().toLocaleString('ru')} ₽)`);
|
this.error.set(`${this.t('errors.invalid_amount')} (макс. ${this.maxAmount().toLocaleString('ru')} ₽)`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -145,7 +145,7 @@ export class CreatePage {
|
|||||||
`${QR_VITANOVA_API}/qr`,
|
`${QR_VITANOVA_API}/qr`,
|
||||||
{
|
{
|
||||||
qrtype: 'QRDynamic',
|
qrtype: 'QRDynamic',
|
||||||
amount: val,
|
...(val !== null ? { amount: val } : {}),
|
||||||
currency: this.currency(),
|
currency: this.currency(),
|
||||||
partnerqrID,
|
partnerqrID,
|
||||||
qrDescription: this.note().trim(),
|
qrDescription: this.note().trim(),
|
||||||
@@ -225,7 +225,7 @@ export class CreatePage {
|
|||||||
this.store.setCreated({
|
this.store.setCreated({
|
||||||
fastcheck: res.fastcheck,
|
fastcheck: res.fastcheck,
|
||||||
code: res.code,
|
code: res.code,
|
||||||
amount: this.amount(),
|
amount: this.amount() ?? null,
|
||||||
expiration: res.expiration
|
expiration: res.expiration
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -235,12 +235,21 @@ export class CreatePage {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onAmountChange(value: number): void {
|
onAmountChange(value: number | null): void {
|
||||||
this.amount.set(value);
|
this.amount.set(value || null);
|
||||||
if (value > 0) this.error.set('');
|
if (value && value > 0) this.error.set('');
|
||||||
}
|
}
|
||||||
|
|
||||||
onNoteChange(value: string): void {
|
onNoteChange(value: string): void {
|
||||||
this.note.set(value);
|
this.note.set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeQr(): void {
|
||||||
|
this.qrImageUrl.set(null);
|
||||||
|
this.qrPolling.set(false);
|
||||||
|
if (this.pollHandle !== null) {
|
||||||
|
clearInterval(this.pollHandle);
|
||||||
|
this.pollHandle = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,10 +55,10 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Share row — shown once amount is known -->
|
<!-- Share row — always visible, enabled once amount is known -->
|
||||||
@if (fastcheckAmount() !== null && !amountLoading()) {
|
|
||||||
<div class="share-row">
|
<div class="share-row">
|
||||||
<button type="button" class="share-btn share-btn--email" (click)="shareByEmail()"
|
<button type="button" class="share-btn share-btn--email" (click)="shareByEmail()"
|
||||||
|
[disabled]="fastcheckAmount() === null || amountLoading()"
|
||||||
[title]="'fastcheck.share_email' | translate">
|
[title]="'fastcheck.share_email' | translate">
|
||||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||||
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
@@ -68,6 +68,7 @@
|
|||||||
{{ 'fastcheck.share_email' | translate }}
|
{{ 'fastcheck.share_email' | translate }}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="share-btn share-btn--tg" (click)="shareByTelegram()"
|
<button type="button" class="share-btn share-btn--tg" (click)="shareByTelegram()"
|
||||||
|
[disabled]="fastcheckAmount() === null || amountLoading()"
|
||||||
[title]="'fastcheck.share_tg' | translate">
|
[title]="'fastcheck.share_tg' | translate">
|
||||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
||||||
<path d="M9.04 15.65l-.36 4.06c.51 0 .73-.22.99-.48l2.38-2.27 4.93 3.6c.9.5 1.55.24 1.79-.83l3.24-15.18h.01c.29-1.34-.48-1.86-1.36-1.54L1.13 9.66c-1.32.5-1.3 1.23-.22 1.56l4.92 1.53L17.27 5.6c.54-.34 1.03-.15.62.19"/>
|
<path d="M9.04 15.65l-.36 4.06c.51 0 .73-.22.99-.48l2.38-2.27 4.93 3.6c.9.5 1.55.24 1.79-.83l3.24-15.18h.01c.29-1.34-.48-1.86-1.36-1.54L1.13 9.66c-1.32.5-1.3 1.23-.22 1.56l4.92 1.53L17.27 5.6c.54-.34 1.03-.15.62.19"/>
|
||||||
@@ -75,7 +76,6 @@
|
|||||||
{{ 'fastcheck.share_tg' | translate }}
|
{{ 'fastcheck.share_tg' | translate }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
|
||||||
|
|
||||||
<!-- Code -->
|
<!-- Code -->
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
|||||||
@@ -40,6 +40,12 @@
|
|||||||
border-color: #bfdbfe;
|
border-color: #bfdbfe;
|
||||||
&:hover { background: #dbeafe; border-color: #93c5fd; }
|
&:hover { background: #dbeafe; border-color: #93c5fd; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: .4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
|
|||||||
Reference in New Issue
Block a user