JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
<script>
//******************* Ignore this code **************************
var counter = 0;
var taskId = null;
function fakeApiValidator(state) {
if (window.taskId === 1) {
return fakeApiValidateCartItemsStateTask1(state);
}
if (window.taskId === 2) {
return fakeApiValidateCartItemsStateTask2(state);
}
}
function fakeApiValidateCartItemsStateTask1(state) {
return new Promise((resolve) => {
state.length === 1 && state.includes('Derila') ?
setTimeout(() => resolve(state), 100) :
resolve(state);
});
}
function fakeApiValidateCartItemsStateTask2(state) {
return new Promise((resolve, reject) => {
window.counter++;
if (window.counter < 3) {
reject('Network outage!');
}
resolve(state);
});
}
//***************************************************************
Alpine.data('component', function() {
return {
cartItemsState: [],
task: null,
addCartItem(name) {
this.addCartItemQueue = this.addCartItemQueue.then(() => {
const newState = this.cartItemsState.concat(name);
return fakeApiValidator(newState)
.catch(() => [])
.then(response => this.cartItemsState = response);
});
return this.addCartItemQueue;
},
// For the first task you only need to edit addCartItem method. Task 1 simulates 3 addCartItem events that happen in a very short period of time. Expected outcome => ['Derila', 'Nuubu', 'Huusk'].
task1() {
this.addCartItemQueue = Promise.resolve();
this.cartItemsState = [];
this.task = null;
window.taskId = 1;
Promise.all([
this.addCartItem('Derila'),
this.addCartItem('Nuubu'),
this.addCartItem('Huusk')
]).then(() => this.task = 1);
},
// For the second task you...
CSS
body {
background: white;
padding: 20px;
font-family: Arial, sans-serif;
background-color: #f0f0f0;
padding: 20px;
}
.component-container {
background-color: #fff;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
padding: 20px;
max-width: 400px;
margin: 0 auto;
}
.component-container button {
background-color: #007bff;
color: #fff;
padding: 10px;
border-radius: 4px;
text-align: center;
cursor: pointer;
transition: background-color 0.3s;
margin-right: 10px;
}
.component-container p {
font-size: 1.2em;
margin-bottom: 10px;
font-weight: bold;
}
.component-container ul {
list-style-type: none;
padding: 0;
}
.component-container li {
padding: 8px;
border-bottom: 1px solid #ddd;
}
.component-container li:last-child {
border-bottom: none;
}
.run-test {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.run-test .alert {
background-color: #f0f0f0 !important;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
text-align: center;
}
.run-test .alert p {
margin: 0;
color: #c00;
font-size: 12px;
}
.run-test .alert p span {
font-weight: normal;
color: black;
}
.run-test .success {
background-color: #9FE582 !important;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
text-align: center;
}
.run-test .success p {
margin: 0;
color: #0B5800;
font-size: 12px;
}
.run-test .success p span {
font-weight: normal;
color: black;
}