"autoload": { "psr-4": { "App\\": "app/", "YourNamespace\\": "yourFolder/"}}
products
должны быть ref
. Сейчас они не реактивны(никак не реагируют на изменения). При этом ты присваииваешь массиву value. То что это хоть как-то работало - очередное чудо.export const useAllMainFiltersStore = defineStore('allMainFilters', () => {
const products = ref([]);
try {
async function getStoreData() {
sidebarResizeStore.updateSidebarVisibility()
const data = await productsData();
products.value = data;
}
getStoreData()
} catch (error) {
console.error('Error:', error);
}
return {
products,
}
})
const route = useRoute();
// продукт делаем вычисляемым, чтоб не городить вотчеров
const product = computed(() => getProductById(route.params.id));
function getProductById(id) {
console.log('products component: ', mainFiltersStore.products) //при первой загрузке всё ок, при перезагрузке страницы всё ломается и пустой массив в придачу
return products.find(product => product.id == id);
}
watch(product, current => {
// проверяем что продукт есть
if (current) fetchComments(current.id);
}, { immediate: true })
reactive
/ref
объекта, чтоб получить эрзац-стор, тупо: // где-нибудь
export const basket = reactive([]); // или ref([]) по вкусу.
// везде где надо
import { basket } from './...'
store
если можно делать так? Потому что сторы учитывают работу в режиме SSR, а также позволяют удобную отладку в случае множества запутанных связей. store
- только pinia
, а не vuex
. Не вижу причин его не использовать.EventBus
: с одной стороны новичку её использовать категорически не рекомендуется, т.к. работа со store
куда удобнее, очевиднее и надёжнее. Однако и совсем отрицать её использование тоже не следует, шина отлично подходит для случаев когда мы имеем дело именно с событиями, а не изменением состояния. Т.е. послать какой-нить notification или лог - самое оно, использовать для изменения basket
, как в вашем случае - нет. {{Route('ChangeLanguage', N)}}
? /en
и /tr
то у тебя будет открываться собственно та версия, которая сохранена в закладках\истории, а не так которая была выбрана.selectLang.selectedIndex = localStorage.getItem(storageKey);
вызовет change
автоматически - это не так, программная смена не вызывает событий.const deleteBaggagePrice = price = price.filter( //проверка price на наличие свойства baggageID
(prop) => !prop.hasOwnProperty("baggageID") //если есь удалить объект
);
const currentObj = currentPassengers.find(item => item.PassengersId === passengerIdEdit)
currentObj.Name = dataName;
currentObj.Surname: dataSurname;
childArr.map(item => { // перебираю все карточки в корзине
.map() обычно используется не для простого перебора, а чтобы вернуть перебранный массив. в первом селекте 1 авто а во втором 2В этому случае «перебираются» 2 элемента через этот .map().
но после повторного добавления авто в корзину возвращаются удаленные карточки
let getCars = JSON.parse(localStorage.getItem(LSKeyCars) || "[]");
Это записывается один раз. А после очистки корзины не переписывается, если не перезагружать страницу. Поэтому карточки берутся из этой переменной, а не из обновлённых данных storage.const CARS_LIMIT = 2;
const optionsBlock = document.querySelector('.parent');
const cart = document.querySelector('.info');
const addOptionButton = document.querySelector('.add');
const addToCartButton = document.querySelector('.btn');
const clearCartButton = document.querySelector('.delete-all');
addOptionButton.addEventListener('click', addOption);
addToCartButton.addEventListener('click', addItemToCart);
clearCartButton.addEventListener('click', clearCart);
optionsBlock.addEventListener('click', ({ target }) => {
if (target.closest('.remove')) {
target.parentNode.remove();
}
});
function addOption() {
optionsBlock.insertAdjacentHTML('beforeend',
`<div class="child">
<span class="remove">✖</span>
<input type="text" class="model" placeholder="Введите модель авто">
<select class="amount">
<option value="" disabled selected>Количество</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</div>`)
}
function clearCart() {
localStorage.removeItem('cars');
renderCart();
}
function addItemToCart() {
const currentCarsState = getStorageState() ?? [];
const carInfoOptions = [...document.querySelectorAll('.child')];
const carsAmount = currentCarsState.reduce((acc, { carAmount }) => acc + carAmount, 0);
const { carsData, selectedAmount } = carInfoOptions.reduce((acc, carInfo) => {
const carAmount = +carInfo.querySelector('.amount').value;
const carModel = carInfo.querySelector('.model').value;
const currentCarData = {
id: Math.floor(Math.random() * 100), //плохой вариант, т.к. случайные числа могут повторяться
carModel,
carAmount,
};
acc.carsData.push(currentCarData);
acc.selectedAmount += carAmount;
return acc;
}, { carsData: [], selectedAmount: 0 })
if (carsAmount + selectedAmount > CARS_LIMIT) {
alert('Количество автомобилей превышает количество взрослых');
return;
}
localStorage.setItem('cars', JSON.stringify([...currentCarsState, ...carsData]));
renderCart();
}
function getStorageState() {
return JSON.parse(localStorage.getItem('cars'));
}
function renderCart() {
const cartData = getStorageState();
cart.innerHTML = !cartData ? '' : cartData.map(car => `<div class="item" id="${car.id}">
<div class="title">ЛИЧНЫЙ ТРАНСПОРТ</div>
<div>Модель авто: ${car.carModel}</div>
<div>Количество авто: ${car.carAmount}</div>
</div>`).join('');
}
<div class="parent__block">
<form class="child__block" data-id="1">
<div class="">name: </div><input type="text" class="name" name="name">
<div class="">surname: </div><input type="text" class="surname" name="surname">
<button type="submit">click</button>
</form>
</div>
<div class="parent__block">
<form class="child__block" data-id="2">
<div class="">name: </div><input type="text" class="name" name="name">
<div class="">surname: </div><input type="text" class="surname" name="surname">
<button type="submit">click</button>
</form>
</div>
const persons = [
{ id: 1, check: 1 },
{ id: 2, check: 0 }
];
const onFormSubmit = (form) => {
form.addEventListener('submit', (event) => {
event.preventDefault();
const id = parseInt(form.dataset.id);
if (!Number.isNaN(id)) {
const formData = new FormData(form);
const person = persons.find((person => person.id === id));
person.name = formData.get('name');
person.surname = formData.get('surname');
console.log(persons);
}
});
};
document
.querySelectorAll('form[data-id]')
.forEach((form) => onFormSubmit(form));
<div class="container">
<div class="cart">
<input class="input amount-one" type="text" value="0" />
<input class="input amount-two" type="text" value="0" />
<input class="input amount-three" type="text" value="0" />
<button class="btn">click</button>
</div>
<div class="cart">
<input class="input amount-one" type="text" value="0" />
<input class="input amount-two" type="text" value="0" />
<input class="input amount-three" type="text" value="0" />
<button class="btn">click</button>
</div>
<div class="box">
<input id="clear" type="button" value="clear all" />
<div class="info"></div>
</div>
</div>
body {
display: flex;
justify-content: center;
background-color: #1d1e22;
}
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.cart {
display: flex;
flex-direction: column;
margin: 20px;
}
.input {
padding-left: 20px;
height: 20px;
margin-bottom: 5px;
font-size: 20px;
border-radius: 10px;
}
.btn {
height: 30px;
font-size: 20px;
border-radius: 10px;
}
.box {
display: flex;
flex-direction: column;
align-items: center;
margin: 20px;
}
#clear {
width: 100px;
height: 40px;
margin-bottom: 10px;
font-size: 20px;
border-radius: 10px;
}
.info {
display: flex;
justify-content: center;
align-items: center;
width: 200px;
height: 30px;
border: 2px solid #bbb;
background-color: #fff;
}
let currentTariff = JSON.parse(localStorage.getItem('cabins') || '[]');
const passengersMax = 3; // Максимальное количество пассажиров
let accommodationSum = currentTariff.reduce((acc, curr) => acc + curr.accommodation, 0);
const btn = document.querySelectorAll('.btn');
const info = document.querySelector('.info');
// Вывести текущие тарифные данные в информационный блок
const render = (tariff = currentTariff) => {
[...tariff].forEach(el => {
info.insertAdjacentHTML('beforeend', `<div>${el.accommodation}</div>`);
});
};
render();
btn.forEach(button => {
button.addEventListener('click', function (e) {
const cart = e.target.closest('.cart');
const countOne = cart.querySelector('.amount-one').value;
const countTwo = cart.querySelector('.amount-two').value;
const countThree = cart.querySelector('.amount-three').value;
const accommodationPass = parseInt(countOne) + parseInt(countTwo) + parseInt(countThree);
if (accommodationSum + accommodationPass > passengersMax) {
alert('В этом заказе вы превысили максимальное количество человек');
return;
}
const obj = {
countOne: countOne,
countTwo: countTwo,
countThree: countThree,
accommodation: parseInt(accommodationPass),
};
// Обновляем текущий тариф и отображаем новые данные
currentTariff.push(obj);
updateState();
const sum = currentTariff.reduce((acc, curr) => acc + curr.accommodation, 0);
info.innerHTML = `<div>Общая сумма: ${sum}</div>`;
accommodationSum = sum; // Устанавливаем сумму размещения на текущую сумму
});
function updateState() {
localStorage.setItem('cabins', JSON.stringify(currentTariff));
}
// Очищаем входы и информационный блок при нажатии кнопки "clear all"
function clearData() {
currentTariff.length = 0;
localStorage.removeItem('cabins');
info.innerHTML = '';
const inputs = document.querySelectorAll('input[type="text"]');
inputs.forEach(input => {
input.value = 0;
});
accommodationSum = 0; // Сбрасываем сумму размещения до 0
}
const clearBtn = document.querySelector('input#clear');
clearBtn.addEventListener('click', clearData);
});
// значения withSeat вместо раскладывания в отдельные переменные собираете в объект
const withSeat = {
adult: 1,
teenager: 1,
babe: 0,
};
const passengers = cabins.flatMap(n => Object
.entries(n)
.flatMap(([ k, v ]) => Array.from(
{ length: v },
() => ({ withSeat: withSeat[k] })
))
);
const renderResult = (result) => {
if (result.result === 0) {
alert("Not found");
} else {
currentItem.push(info);
render([info]);
update();
}
};
if (item < 0) {
alert("not render")
} else {
fetch(url, options)
.then((response) => response.json())
.then(renderResult)
}
if (item < 0) return;
const response = await fetch(url, options);
const result = await response.json();
if (result.result === 0) return;
currentItem.push(info);
render([info]);
update();
document.addEventListener('click', updateCounter);
document.addEventListener('input', updateCounter);
document.querySelectorAll('.tariff__counter').forEach(n => {
const max = n.dataset.seats;
n.querySelectorAll('.tariff__counter-max').forEach(m => m.innerText = max);
n.querySelectorAll('.amount').forEach(m => m.max = max);
n.querySelectorAll('button').forEach(m => m.dataset.change = m.innerText === '+' ? 1 : -1);
});
function updateCounter({ target: t }) {
const input = t.closest('.tariff__counter-block')?.querySelector('.amount');
if (input) {
const { min, max, value } = input;
input.value = Math.max(min, Math.min(max, (value | 0) + (t.dataset.change | 0)));
}
}
<span class="animals" data-allowed="{{$cabin->HasAnimals}}">
{{$cabin->HasAnimals?Translate::GetTranslation('Animals Allowed'):Translate::GetTranslation('Animals Not Allowed')}}
</span>
const span = document.querySelector('span.animals');
const isAnimalsAllowed = !!span.dataset.allowed;
span
бэк отрисовывает