feat(ticket-selector): simplify validation handling and remove unused validation UI elements
This commit is contained in:
@@ -17,31 +17,7 @@
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="ticket-selector__selection">
|
<div class="ticket-selector__selection">
|
||||||
<div class="ticket-selector__label-row">
|
<span class="ticket-selector__label">Seleccioná Entrada/s:</span>
|
||||||
<span class="ticket-selector__label">Seleccioná Entrada/s:</span>
|
|
||||||
@if (validationStatus(); as status) {
|
|
||||||
<span
|
|
||||||
class="ticket-selector__validation ticket-selector__validation--{{ status }}"
|
|
||||||
role="status"
|
|
||||||
aria-live="polite"
|
|
||||||
>
|
|
||||||
@switch (status) {
|
|
||||||
@case ('validating') {
|
|
||||||
<span class="ticket-selector__validation-spinner" aria-hidden="true"></span>
|
|
||||||
Validando
|
|
||||||
}
|
|
||||||
@case ('validated') {
|
|
||||||
<i class="fa-solid fa-check" aria-hidden="true"></i>
|
|
||||||
Validado
|
|
||||||
}
|
|
||||||
@case ('error') {
|
|
||||||
<i class="fa-solid fa-xmark" aria-hidden="true"></i>
|
|
||||||
Error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="ticket-selector__rows">
|
<div class="ticket-selector__rows">
|
||||||
@for (row of rows(); track row.id) {
|
@for (row of rows(); track row.id) {
|
||||||
|
|||||||
@@ -44,49 +44,14 @@
|
|||||||
padding-top: 1rem;
|
padding-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__label-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.65rem;
|
|
||||||
min-height: 1.5rem;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__label {
|
&__label {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
color: #555;
|
color: #555;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__validation {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.3rem;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: 600;
|
|
||||||
|
|
||||||
&--validating {
|
|
||||||
color: #777;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--validated {
|
|
||||||
color: var(--success-color, #198754);
|
|
||||||
}
|
|
||||||
|
|
||||||
&--error {
|
|
||||||
color: var(--danger-color, #dc3545);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__validation-spinner {
|
|
||||||
width: 0.8rem;
|
|
||||||
height: 0.8rem;
|
|
||||||
border: 2px solid currentcolor;
|
|
||||||
border-right-color: transparent;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: ticket-selector-spin 0.7s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__rows {
|
&__rows {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
@@ -150,18 +115,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes ticket-selector-spin {
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
.ticket-selector__validation-spinner {
|
|
||||||
animation-duration: 1.4s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 767.98px) {
|
@media (max-width: 767.98px) {
|
||||||
.ticket-selector {
|
.ticket-selector {
|
||||||
&__header {
|
&__header {
|
||||||
|
|||||||
@@ -160,9 +160,6 @@ describe('ProductTicketSelectorComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const validation = fixture.nativeElement.querySelector('.ticket-selector__validation');
|
|
||||||
expect(validation.textContent).toContain('Validado');
|
|
||||||
expect(validation.querySelector('.fa-check')).not.toBeNull();
|
|
||||||
expect(fixture.nativeElement.querySelector('.ticket-selector__row-status')).toBeNull();
|
expect(fixture.nativeElement.querySelector('.ticket-selector__row-status')).toBeNull();
|
||||||
expect(fixture.nativeElement.querySelector('.ticket-selector__row-error')).toBeNull();
|
expect(fixture.nativeElement.querySelector('.ticket-selector__row-error')).toBeNull();
|
||||||
|
|
||||||
@@ -283,9 +280,6 @@ describe('ProductTicketSelectorComponent', () => {
|
|||||||
'Sector A',
|
'Sector A',
|
||||||
'1',
|
'1',
|
||||||
]);
|
]);
|
||||||
expect(
|
|
||||||
fixture.nativeElement.querySelector('.ticket-selector__validation').textContent,
|
|
||||||
).toContain('Validado');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('keeps the reserved selection and shows a toast when a variant change cannot be completed', async () => {
|
it('keeps the reserved selection and shows a toast when a variant change cannot be completed', async () => {
|
||||||
|
|||||||
@@ -36,8 +36,6 @@ type TicketSelectionStatus =
|
|||||||
| 'removing'
|
| 'removing'
|
||||||
| 'error';
|
| 'error';
|
||||||
|
|
||||||
type TicketValidationStatus = 'validating' | 'validated' | 'error';
|
|
||||||
|
|
||||||
interface TicketSelectionRow {
|
interface TicketSelectionRow {
|
||||||
id: number;
|
id: number;
|
||||||
variantId: number | null;
|
variantId: number | null;
|
||||||
@@ -92,15 +90,6 @@ export class ProductTicketSelectorComponent {
|
|||||||
row.variantId === row.reservedVariantId,
|
row.variantId === row.reservedVariantId,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
protected readonly validationStatus = computed<TicketValidationStatus | null>(() => {
|
|
||||||
const rows = this.rows();
|
|
||||||
|
|
||||||
if (rows.some((row) => this.isBusy(row))) return 'validating';
|
|
||||||
if (rows.some((row) => row.status === 'error' || row.error !== null)) return 'error';
|
|
||||||
if (rows.length > 0 && rows.every((row) => row.status === 'reserved')) return 'validated';
|
|
||||||
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
protected readonly canAddRow = computed(
|
protected readonly canAddRow = computed(
|
||||||
() =>
|
() =>
|
||||||
this.availableVariantCount() > 0 &&
|
this.availableVariantCount() > 0 &&
|
||||||
|
|||||||
Reference in New Issue
Block a user