 
  
  serverAndUserTimeDifference — разница в миллисекундах между датами, а при пробросе её в moment() она считается как дата в UNIX-формате.const now = moment();
const serverTime = moment('2024-10-09 10:20:34.987');
const duration = moment.duration(Math.abs(now.diff(serverTime)));
const result = `${duration.days()} ${duration.hours().toString().padStart(2, '0')}:${duration.minutes().toString().padStart(2, '0')}:${duration.seconds().toString().padStart(2, '0')}`;this.$set \ Vue.set при добавлении нового ключа.const templates = reactive(keyBy(templatesArr, 'id'))
for (let templateId in templates) {
  const devices = devicesArr.filter(device => device.templateId === templateId)
  Vue.set(templates[templateId], 'devices', devices);
  Vue.set(templates[templateId], 'settings', {});
}
// либо просто так:
const templates = keyBy(templatesArr, 'id');
for (let templateId in templates) {
  const devices = devicesArr.filter(device => device.templateId === templateId)
  Object.assign(templates[templateId], { devices }, {settings: {}})
}
reactive(templates);reactive, вместо него был Vue.observable. Но может добавили, хз, лень смотреть.:)       
  
  почему при изменении даты передаваемой в пропс не обновляется значение в самом компоненте таймера?
targetDate при изменении props.date. Нет, можете себя не утруждать - ничего такого у вас нет.targetDate, рассчитываем дни-часы-минуты-секунды сразу на основе props.date - так при изменении props.date не придётся предпринимать никаких дополнительных телодвижений, всё посчитается как надо при следующем вызове updateCountdown. Вот как-то так.       
  
  const updateItems = async ({ id, isShow = false }: Partial<{ id: number, isShow: boolean }>) => {}; 
  
  var o = {
    value: {
        orders: {
            tools: [
                {
                    tool1: 't1'
                }
            ],
            wood: [
                {
                    wood1: 'w1',
                }
            ],
        },
    }
}
var allOrders = [];
var ordersByType = o.value?.orders || {};
Object.keys(ordersByType).forEach((type) => {
    ordersByType[type].forEach((order) => {
        allOrders.push({
            ...order,
            type,
        });
    });
});
o.value.orders = allOrders;const popup = document.querySelector('.popup');
const pseudoElement = popup.querySelector('::before');
popup.addEventListener('scroll', function() {
  if (popup.scrollHeight - popup.scrollTop === popup.clientHeight) {
    pseudoElement.style.display = 'none';
  } else {
    pseudoElement.style.display = 'block';
  }
});const doSmth = () => {
   const event = new Event('doSmth');
   window.dispatchEvent(event);
   console.log('do something')
} 
  
  const event = new Event('myEvent'); // создаем кастомное событие myEvent
pew.addEventListener('click', function() { // слушаем клик по кнопке
  circle.dispatchEvent(event); // отправляем событие myEvent
});
circle.addEventListener('myEvent', function(evt) { // слушаем событие myEvent
  // какая-то полезная нагрузка
  console.log(evt.target);
});