feat: delete report by admin updated

This commit is contained in:
Angie 2025-07-26 20:50:14 +02:00
parent 6cf32f119e
commit bd2d19a543
2 changed files with 209 additions and 90 deletions

View File

@ -351,6 +351,7 @@ async function getReports() {
},
});
const data = await response.json();
console.log(data);
if (response.ok) {
return { success: true, reports: data.reports };
} else {
@ -401,9 +402,6 @@ async function loadReports() {
tbody.innerHTML = "";
reports.forEach((report) => {
const store = database.stores.find((s) => s.id === report.storeId);
// Fallback for username if user might be missing from local array:
const user = database.users.find((u) => u.id === report.userId);
const profit =
(Number(report.totalIncome) || 0) - (Number(report.totalExpenses) || 0);
@ -426,7 +424,7 @@ async function loadReports() {
profit >= 0 ? "text-green-600" : "text-red-600"
}">${profit.toFixed(2)}</td>
<td class="px-6 py-4 text-sm text-gray-900">${
user ? user.username : report.userId
report.username || report.userId
}</td>
<td class="px-6 py-4">
<span class="px-2 py-1 text-xs rounded-full ${
@ -470,8 +468,6 @@ function viewReport(reportId) {
}
}
//create report
// createReport(data)
//edit report
async function updateReport(reportId, data) {
const token = localStorage.getItem("token");
@ -490,6 +486,8 @@ async function updateReport(reportId, data) {
hideModal("reportViewModal");
await loadReports();
console.log(data);
if (typeof updateDashboard === "function") updateDashboard();
return { success: true };
} else {
@ -602,15 +600,32 @@ function editReport(report) {
}
async function saveEditedReport(reportId) {
const data = {
storeId: parseInt(document.getElementById("editStoreSelect").value, 10),
reportDate: document.getElementById("editDate").value,
income: parseFloat(document.getElementById("editIncome").value),
initialCash: parseFloat(document.getElementById("editCajaInicial").value),
envelope: parseFloat(document.getElementById("editEnvelope").value),
isVerified: document.getElementById("editVerified").checked ? 1 : 0,
};
data.totalIncome = data.income + data.initialCash;
// Get values from the form
const storeId = document.getElementById("editStoreSelect").value;
const reportDate = document.getElementById("editDate").value;
const incomeVal = document.getElementById("editIncome").value;
const initialCashVal = document.getElementById("editCajaInicial").value;
const envelopeVal = document.getElementById("editEnvelope").value;
const isVerified = document.getElementById("editVerified").checked ? 1 : 0;
// Build the payload dynamically
const data = {};
if (storeId) data.storeId = parseInt(storeId, 10);
if (reportDate) data.reportDate = reportDate;
if (incomeVal !== "") data.income = parseFloat(incomeVal);
if (initialCashVal !== "") data.initialCash = parseFloat(initialCashVal);
if (envelopeVal !== "") data.envelope = parseFloat(envelopeVal);
if (data.income !== undefined && data.initialCash !== undefined) {
data.totalIncome = data.income + data.initialCash;
}
data.isVerified = isVerified;
// REMOVE any NaN values
Object.keys(data).forEach((k) => {
if (typeof data[k] === "number" && isNaN(data[k])) delete data[k];
});
await updateReport(reportId, data);
}
@ -645,5 +660,57 @@ async function verifyReport(reportId) {
}
}
//delete report
// deleteReport(id)
//delete report (admin only)
async function apiDeleteReport(reportId) {
const token = localStorage.getItem("token");
try {
const response = await fetch(`${API_BASE_URL}/reports/${reportId}`, {
method: "DELETE",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
});
const data = await response.json();
if (response.ok && data.deleted) {
showNotification("Отчет удален!");
await loadReports();
if (typeof updateDashboard === "function") updateDashboard();
} else {
showNotification(data.error || "Ошибка удаления отчета", "error");
}
} catch {
showNotification("Нет соединения с сервером", "error");
}
}
//worker
//create report
// api.js
async function createReport(data) {
const token = localStorage.getItem("token");
try {
const response = await fetch(`${API_BASE_URL}/reports`, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
const result = await response.json();
if (response.ok && result.id) {
return { success: true, id: result.id };
} else {
return {
success: false,
error:
result.error ||
(result.errors && result.errors[0]?.msg) ||
"Ошибка создания отчета",
};
}
} catch (err) {
return { success: false, error: "Нет соединения с сервером" };
}
}

View File

@ -256,11 +256,9 @@ function loadUserStores() {
let userStores = [];
if (currentUser.role === "admin") {
userStores = database.stores;
userStores = currentUser.stores;
} else {
userStores = database.stores.filter((store) =>
currentUser.stores.includes(store.id)
);
userStores = currentUser.stores;
}
userStores.forEach((store) => {
@ -405,85 +403,133 @@ function updateTotals() {
}
// Отправка формы отчета
document.getElementById("reportForm").addEventListener("submit", (e) => {
// document.getElementById("reportForm").addEventListener("submit", (e) => {
// e.preventDefault();
// const formData = {
// id: editingReportId || Date.now(),
// date: new Date().toISOString().split("T")[0],
// storeId: parseInt(document.getElementById("storeSelect").value),
// userId: currentUser.id,
// income: parseFloat(document.getElementById("income").value),
// cajaInicial: parseFloat(document.getElementById("cajaInicial").value),
// totalIncome: parseFloat(document.getElementById("totalIncome").value),
// envelope: parseFloat(document.getElementById("envelope").value),
// verified: false,
// createdAt: new Date().toISOString(),
// };
// // Сбор зарплат
// const wages = [];
// const wageRows = document.querySelectorAll(".wage-row");
// wageRows.forEach((row) => {
// const name = row.querySelector(".wage-name").value;
// const amount = parseFloat(row.querySelector(".wage-amount").value) || 0;
// if (name && amount > 0) {
// wages.push({ name, amount });
// }
// });
// // Сбор расходов
// const expenses = [];
// const expenseRows = document.querySelectorAll(".expense-row");
// expenseRows.forEach((row) => {
// const name = row.querySelector(".expense-name").value;
// const amount = parseFloat(row.querySelector(".expense-amount").value) || 0;
// if (name && amount > 0) {
// expenses.push({ name, amount });
// }
// });
// formData.wages = wages;
// formData.expenses = expenses;
// formData.totalWages = calculateTotalWages();
// formData.totalExpensesInternal = calculateTotalExpenses();
// formData.totalExpenses = formData.totalWages + formData.totalExpensesInternal;
// formData.cajaFinal =
// formData.totalIncome - formData.totalExpenses - formData.envelope;
// if (editingReportId) {
// const index = database.reports.findIndex((r) => r.id === editingReportId);
// database.reports[index] = formData;
// editingReportId = null;
// showNotification("Отчет успешно обновлен!");
// } else {
// database.reports.push(formData);
// showNotification("Отчет успешно сохранен!");
// }
// // Очистка формы
// document.getElementById("reportForm").reset();
// document.getElementById("wagesContainer").innerHTML = `
// <div class="wage-row grid grid-cols-1 md:grid-cols-3 gap-4 mb-3">
// <input type="text" placeholder="Имя сотрудника" class="wage-name form-input px-3 py-2 rounded-lg">
// <input type="number" step="0.01" placeholder="Сумма €" class="wage-amount form-input px-3 py-2 rounded-lg">
// <button type="button" class="remove-wage bg-red-500 text-white px-3 py-2 rounded-lg hover:bg-red-600 transition-colors">
// <i class="fas fa-times"></i>
// </button>
// </div>
// `;
// document.getElementById("expensesContainer").innerHTML = `
// <div class="expense-row grid grid-cols-1 md:grid-cols-3 gap-4 mb-3">
// <input type="text" placeholder="Название расхода" class="expense-name form-input px-3 py-2 rounded-lg">
// <input type="number" step="0.01" placeholder="Сумма €" class="expense-amount form-input px-3 py-2 rounded-lg">
// <button type="button" class="remove-expense bg-red-500 text-white px-3 py-2 rounded-lg hover:bg-red-600 transition-colors">
// <i class="fas fa-times"></i>
// </button>
// </div>
// `;
// updateTotals();
// });
document.getElementById("reportForm").addEventListener("submit", async (e) => {
e.preventDefault();
const formData = {
id: editingReportId || Date.now(),
date: new Date().toISOString().split("T")[0],
storeId: parseInt(document.getElementById("storeSelect").value),
userId: currentUser.id,
reportDate: new Date().toISOString().split("T")[0], // Or get from input if user chooses date
income: parseFloat(document.getElementById("income").value),
cajaInicial: parseFloat(document.getElementById("cajaInicial").value),
initialCash: parseFloat(document.getElementById("cajaInicial").value),
totalIncome: parseFloat(document.getElementById("totalIncome").value),
wages: JSON.stringify(collectWages()),
expenses: JSON.stringify(collectExpenses()),
totalWages: calculateTotalWages(),
totalExpenses: calculateTotalExpenses() + calculateTotalWages(),
envelope: parseFloat(document.getElementById("envelope").value),
verified: false,
createdAt: new Date().toISOString(),
finalCash:
parseFloat(document.getElementById("totalIncome").value) -
(calculateTotalWages() + calculateTotalExpenses()) -
parseFloat(document.getElementById("envelope").value),
};
console.log("Sending report:", formData);
const result = await createReport(formData);
if (result.success) {
showNotification("Отчет успешно создан!");
document.getElementById("reportForm").reset();
} else {
showNotification(result.error || "Ошибка создания отчета", "error");
}
});
// Сбор зарплат
function collectWages() {
const wages = [];
const wageRows = document.querySelectorAll(".wage-row");
wageRows.forEach((row) => {
document.querySelectorAll(".wage-row").forEach((row) => {
const name = row.querySelector(".wage-name").value;
const amount = parseFloat(row.querySelector(".wage-amount").value) || 0;
if (name && amount > 0) {
wages.push({ name, amount });
}
if (name && amount > 0) wages.push({ name, amount });
});
// Сбор расходов
return wages;
}
function collectExpenses() {
const expenses = [];
const expenseRows = document.querySelectorAll(".expense-row");
expenseRows.forEach((row) => {
document.querySelectorAll(".expense-row").forEach((row) => {
const name = row.querySelector(".expense-name").value;
const amount = parseFloat(row.querySelector(".expense-amount").value) || 0;
if (name && amount > 0) {
expenses.push({ name, amount });
}
if (name && amount > 0) expenses.push({ name, amount });
});
formData.wages = wages;
formData.expenses = expenses;
formData.totalWages = calculateTotalWages();
formData.totalExpensesInternal = calculateTotalExpenses();
formData.totalExpenses = formData.totalWages + formData.totalExpensesInternal;
formData.cajaFinal =
formData.totalIncome - formData.totalExpenses - formData.envelope;
if (editingReportId) {
const index = database.reports.findIndex((r) => r.id === editingReportId);
database.reports[index] = formData;
editingReportId = null;
showNotification("Отчет успешно обновлен!");
} else {
database.reports.push(formData);
showNotification("Отчет успешно сохранен!");
}
// Очистка формы
document.getElementById("reportForm").reset();
document.getElementById("wagesContainer").innerHTML = `
<div class="wage-row grid grid-cols-1 md:grid-cols-3 gap-4 mb-3">
<input type="text" placeholder="Имя сотрудника" class="wage-name form-input px-3 py-2 rounded-lg">
<input type="number" step="0.01" placeholder="Сумма €" class="wage-amount form-input px-3 py-2 rounded-lg">
<button type="button" class="remove-wage bg-red-500 text-white px-3 py-2 rounded-lg hover:bg-red-600 transition-colors">
<i class="fas fa-times"></i>
</button>
</div>
`;
document.getElementById("expensesContainer").innerHTML = `
<div class="expense-row grid grid-cols-1 md:grid-cols-3 gap-4 mb-3">
<input type="text" placeholder="Название расхода" class="expense-name form-input px-3 py-2 rounded-lg">
<input type="number" step="0.01" placeholder="Сумма €" class="expense-amount form-input px-3 py-2 rounded-lg">
<button type="button" class="remove-expense bg-red-500 text-white px-3 py-2 rounded-lg hover:bg-red-600 transition-colors">
<i class="fas fa-times"></i>
</button>
</div>
`;
updateTotals();
});
return expenses;
}
// Отчет за сегодня для пользователя
document.getElementById("todayReportBtn").addEventListener("click", () => {
@ -510,9 +556,6 @@ function showReportModal(report, isAdmin = false) {
const buttons = document.getElementById("reportModalButtons");
const title = document.getElementById("reportModalTitle");
const store = database.stores.find((s) => s.id === report.storeId);
const user = database.users.find((u) => u.id === report.userId);
title.textContent = `Отчет от ${report.reportDate || report.date} - ${
report.storeName || report.storeId || "Неизвестный магазин"
}`;
@ -530,7 +573,7 @@ function showReportModal(report, isAdmin = false) {
report.storeName || report.storeId
}</div>
<div><strong>Пользователь:</strong> ${
user ? user.username : report.userId
report.username || report.fullName || report.userId
}</div>
<div><strong>Статус:</strong>
<span class="px-2 py-1 rounded text-xs ${
@ -1232,13 +1275,22 @@ function createCharts() {
// }
// Удаление отчета
// function deleteReport(reportId) {
// if (confirm("Вы уверены, что хотите удалить этот отчет?")) {
// database.reports = database.reports.filter((r) => r.id !== reportId);
// loadReports();
// updateDashboard();
// showNotification("Отчет удален!");
// }
// }
function deleteReport(reportId) {
if (confirm("Вы уверены, что хотите удалить этот отчет?")) {
database.reports = database.reports.filter((r) => r.id !== reportId);
showConfirmModal("Вы уверены, что хотите удалить этот отчет?", () => {
apiDeleteReport(reportId);
loadReports();
updateDashboard();
showNotification("Отчет удален!");
}
});
}
// Настройка фильтров отчетов