feat(pos): add editable showcase creation date for kits
- Add showcase_created_at field to ProductKit model - Display days ago as badge in product card (0 дней, 1 день, etc.) - Add date input field in edit modal - Auto-set current date/time for new showcase kits Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -98,6 +98,37 @@ function formatMoney(v) {
|
||||
return (Number(v)).toFixed(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Форматирует дату как относительное время в русском языке
|
||||
* @param {string|null} isoDate - ISO дата или null
|
||||
* @returns {string} - "0 дней", "1 день", "2 дня", "5 дней", и т.д.
|
||||
*/
|
||||
function formatDaysAgo(isoDate) {
|
||||
if (!isoDate) return '';
|
||||
|
||||
const created = new Date(isoDate);
|
||||
const now = new Date();
|
||||
const diffMs = now - created;
|
||||
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
||||
|
||||
// Русские формы множественного числа
|
||||
const lastTwo = diffDays % 100;
|
||||
const lastOne = diffDays % 10;
|
||||
|
||||
let suffix;
|
||||
if (lastTwo >= 11 && lastTwo <= 19) {
|
||||
suffix = 'дней';
|
||||
} else if (lastOne === 1) {
|
||||
suffix = 'день';
|
||||
} else if (lastOne >= 2 && lastOne <= 4) {
|
||||
suffix = 'дня';
|
||||
} else {
|
||||
suffix = 'дней';
|
||||
}
|
||||
|
||||
return `${diffDays} ${suffix}`;
|
||||
}
|
||||
|
||||
// ===== ФУНКЦИИ ДЛЯ РАБОТЫ С КЛИЕНТОМ =====
|
||||
|
||||
/**
|
||||
@@ -911,7 +942,7 @@ function renderProducts() {
|
||||
const stock = document.createElement('div');
|
||||
stock.className = 'product-stock';
|
||||
|
||||
// Для витринных комплектов показываем название витрины И количество (доступно/всего)
|
||||
// Для витринных комплектов показываем количество (доступно/всего) и дней на витрине
|
||||
if (item.type === 'showcase_kit') {
|
||||
const availableCount = item.available_count || 0;
|
||||
const totalCount = item.total_count || availableCount;
|
||||
@@ -922,7 +953,14 @@ function renderProducts() {
|
||||
let badgeText = totalCount > 1 ? `${availableCount}/${totalCount}` : `${availableCount}`;
|
||||
let cartInfo = inCart > 0 ? ` <span class="badge bg-warning text-dark">🛒${inCart}</span>` : '';
|
||||
|
||||
stock.innerHTML = `🌺 ${item.showcase_name} <span class="badge ${badgeClass} ms-1">${badgeText}</span>${cartInfo}`;
|
||||
// Добавляем отображение дней с момента создания как бейдж справа
|
||||
const daysAgo = formatDaysAgo(item.showcase_created_at);
|
||||
const daysBadge = daysAgo ? ` <span class="badge bg-info ms-auto">${daysAgo}</span>` : '';
|
||||
|
||||
stock.innerHTML = `<span class="badge ${badgeClass}" style="font-size: 0.9rem;">${badgeText}</span>${daysBadge}${cartInfo}`;
|
||||
stock.style.display = 'flex';
|
||||
stock.style.justifyContent = 'space-between';
|
||||
stock.style.alignItems = 'center';
|
||||
stock.style.color = '#856404';
|
||||
stock.style.fontWeight = 'bold';
|
||||
} else if (item.type === 'product' && item.available_qty !== undefined && item.reserved_qty !== undefined) {
|
||||
@@ -1837,6 +1875,19 @@ async function openEditKitModal(kitId) {
|
||||
// Заполняем поля формы
|
||||
document.getElementById('tempKitName').value = kit.name;
|
||||
document.getElementById('tempKitDescription').value = kit.description;
|
||||
|
||||
// Заполняем поле даты размещения на витрине
|
||||
if (kit.showcase_created_at) {
|
||||
// Конвертируем ISO в формат datetime-local (YYYY-MM-DDTHH:MM)
|
||||
const date = new Date(kit.showcase_created_at);
|
||||
// Компенсация смещения часового пояса
|
||||
const offset = date.getTimezoneOffset() * 60000;
|
||||
const localDate = new Date(date.getTime() - offset);
|
||||
document.getElementById('showcaseCreatedAt').value = localDate.toISOString().slice(0, 16);
|
||||
} else {
|
||||
document.getElementById('showcaseCreatedAt').value = '';
|
||||
}
|
||||
|
||||
document.getElementById('priceAdjustmentType').value = kit.price_adjustment_type;
|
||||
document.getElementById('priceAdjustmentValue').value = kit.price_adjustment_value;
|
||||
|
||||
@@ -2275,8 +2326,9 @@ document.getElementById('confirmCreateTempKit').onclick = async () => {
|
||||
const kitName = document.getElementById('tempKitName').value.trim();
|
||||
const showcaseId = document.getElementById('showcaseSelect').value;
|
||||
const description = document.getElementById('tempKitDescription').value.trim();
|
||||
const showcaseCreatedAt = document.getElementById('showcaseCreatedAt').value;
|
||||
const photoFile = document.getElementById('tempKitPhoto').files[0];
|
||||
|
||||
|
||||
// Валидация
|
||||
if (!kitName) {
|
||||
alert('Введите название комплекта');
|
||||
@@ -2329,6 +2381,12 @@ document.getElementById('confirmCreateTempKit').onclick = async () => {
|
||||
formData.append('quantity', showcaseKitQuantity); // Количество экземпляров на витрину
|
||||
}
|
||||
formData.append('description', description);
|
||||
if (showcaseCreatedAt) {
|
||||
formData.append('showcase_created_at', showcaseCreatedAt);
|
||||
console.log('[DEBUG] Sending showcase_created_at:', showcaseCreatedAt);
|
||||
} else {
|
||||
console.log('[DEBUG] showcase_created_at is empty, NOT sending');
|
||||
}
|
||||
formData.append('items', JSON.stringify(items));
|
||||
formData.append('price_adjustment_type', priceAdjustmentType);
|
||||
formData.append('price_adjustment_value', priceAdjustmentValue);
|
||||
@@ -2398,6 +2456,7 @@ document.getElementById('confirmCreateTempKit').onclick = async () => {
|
||||
|
||||
// Сбрасываем поля формы
|
||||
document.getElementById('tempKitDescription').value = '';
|
||||
document.getElementById('showcaseCreatedAt').value = '';
|
||||
document.getElementById('tempKitPhoto').value = '';
|
||||
document.getElementById('photoPreview').style.display = 'none';
|
||||
document.getElementById('priceAdjustmentType').value = 'none';
|
||||
|
||||
Reference in New Issue
Block a user