Merge remote-tracking branch 'origin/master' into Development

This commit is contained in:
Simon Pocrnjič
2026-01-10 20:45:59 +01:00
5 changed files with 405 additions and 0 deletions
+122
View File
@@ -124,6 +124,128 @@ function formatDate(value) {
return value;
}
}
function toggleAllColumns(checked) {
exportColumns.value = checked ? exportableColumns.map((col) => col.key) : [];
}
function openExportDialog() {
exportDialogOpen.value = true;
exportError.value = "";
}
function closeExportDialog() {
exportDialogOpen.value = false;
}
async function submitExport() {
if (exportColumns.value.length === 0) {
exportError.value = "Izberi vsaj en stolpec.";
return;
}
try {
exportError.value = "";
isExporting.value = true;
const payload = {
scope: exportScope.value,
columns: [...exportColumns.value],
from: fromDate.value || "",
to: toDate.value || "",
search: search.value || "",
segments:
selectedSegments.value.length > 0
? selectedSegments.value.map((s) => s.id).join(",")
: "",
page: props.contracts.current_page,
per_page: props.contracts.per_page,
};
const response = await axios.post(
route("client.contracts.export", { uuid: props.client.uuid }),
payload,
{ responseType: "blob" }
);
const blob = new Blob([response.data], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
const filename =
extractFilenameFromHeaders(response.headers) || buildDefaultFilename();
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
exportDialogOpen.value = false;
} catch (error) {
console.error("Export error:", error);
console.error("Error response:", error.response);
let errorMessage = "Izvoz je spodletel. Poskusi znova.";
if (error.response?.status === 404) {
errorMessage = "Pot za izvoz ne obstaja. Prosim kontaktiraj administratorja.";
} else if (error.response?.status === 500) {
errorMessage = "Napaka na strežniku. Poskusi znova.";
} else if (error.response?.data) {
try {
const text = await error.response.data.text();
const json = JSON.parse(text);
errorMessage = json.message || errorMessage;
} catch (e) {
console.error("Could not parse error response:", e);
}
}
exportError.value = errorMessage;
} finally {
isExporting.value = false;
}
}
function slugify(value) {
if (!value) {
return "data";
}
const slug = value.replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "");
return slug || "data";
}
function buildDefaultFilename() {
const now = new Date();
const dd = String(now.getDate()).padStart(2, "0");
const mm = String(now.getMonth() + 1).padStart(2, "0");
const yy = String(now.getFullYear()).slice(-2);
const clientName = props.client?.person?.full_name || "stranka";
return `${dd}${mm}${yy}_${slugify(clientName)}-Pogodbe.xlsx`;
}
function extractFilenameFromHeaders(headers) {
if (!headers) {
return null;
}
const disposition =
headers["content-disposition"] || headers["Content-Disposition"] || "";
if (!disposition) {
return null;
}
const utf8Match = disposition.match(/filename\*=UTF-8''([^;]+)/i);
if (utf8Match?.[1]) {
try {
return decodeURIComponent(utf8Match[1]);
} catch (error) {
return utf8Match[1];
}
}
const asciiMatch = disposition.match(/filename="?([^";]+)"?/i);
return asciiMatch?.[1] || null;
}
</script>
<template>