Files
taxes/project/assets/controllers/app_controller.js
T
2026-07-08 14:47:53 +02:00

171 lines
4.9 KiB
JavaScript

import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = [
'railStep', 'step', 'accentDot', 'choiceLabel', 'dropzone',
'input', 'chips', 'submitBtn', 'addMore', 'error', 'result','loading-all',
];
static values = {
step: { type: Number, default: 1 },
hash: { type: String, default: '' },
showUrl: {type: String, default: null },
};
connect() {
this.type = null;
this.endpointUrl=null;
this.files = [];
if(this.showUrlValue !== null) {
this.loadTable();
this.stepValue = 0;
}
this.render();
}
// ---- nawigacja ----
pick(event) {
const btn = event.currentTarget;
this.type = btn.dataset.type;
this.choiceLabelTarget.textContent = btn.dataset.label;
this.accentDotTarget.style.background = this.accent;
this.endpointUrl = btn.dataset.endpoint;
this.files = [];
this.updateChips();
this.hideError();
this.stepValue = 2;
}
back() {
if (this.stepValue <= 2) {
this.type = null;
this.stepValue = 1;
} else {
this.stepValue = 2;
}
}
restart() {
this.type = null;
this.files = [];
this.updateChips();
this.resultTarget.innerHTML = '';
this.hideError();
this.stepValue = 1;
// window.history.pushState(null, null, "/");
}
// ---- pliki ----
openPicker() {
this.inputTarget.click();
}
onFiles() {
this.files = Array.from(this.inputTarget.files || []);
this.updateChips();
}
dragOver(event) {
event.preventDefault();
this.dropzoneTarget.classList.add('is-drag');
}
dragLeave() {
this.dropzoneTarget.classList.remove('is-drag');
}
drop(event) {
event.preventDefault();
this.dropzoneTarget.classList.remove('is-drag');
this.files = Array.from(event.dataTransfer.files || []);
this.updateChips();
}
async submit() {
if (this.files.length === 0) {
this.openPicker();
return;
}
this.hideError();
this.setLoading(true);
try {
const fd = new FormData();
fd.append('typ', this.type);
this.files.forEach((f) => fd.append('pliki[]', f));
const res = await fetch(this.endpointUrl, { method: 'POST', body: fd });
if (!res.ok) throw new Error('Błąd serwera (' + res.status + ')');
// const hashSummary = res.url.replace(/^https?:\/\/[^/]+\//, "/").replace(this.endpointUrl, "");
// window.history.pushState(null, null, hashSummary);
this.resultTarget.innerHTML = await res.text();
this.stepValue = 3;
} catch (err) {
this.showError(err.message || 'Nie udało się obliczyć zestawienia.');
} finally {
this.setLoading(false);
}
}
async loadTable(){
this.setLoading(true);
try {
const res = await fetch(this.showUrlValue, { method: 'GET'});
if(!res.ok){
throw new Error('Błąd serwera (' + res.status + ')');
}
this.resultTarget.innerHTML = await res.text();
this.stepValue = 3;
}catch (err) {
this.showError(err.message || 'Nie udało się zaladowac zestawienia.');
} finally {
this.setLoading(false);
}
}
// ---- reakcja na zmianę kroku ----
stepValueChanged() {
this.render();
}
render() {
this.stepTargets.forEach((el) => {
el.hidden = Number(el.dataset.step) !== this.stepValue;
});
this.railStepTargets.forEach((el) => {
const idx = Number(el.dataset.index);
el.classList.toggle('is-active', idx === this.stepValue);
el.classList.toggle('is-done', idx < this.stepValue);
});
}
// ---- helpery ----
get accent() {
return this.type === 'krypto' ? '#C79A3A' : '#3F8F6B';
}
updateChips() {
const has = this.files.length > 0;
this.chipsTarget.hidden = !has;
this.addMoreTarget.hidden = !has;
this.chipsTarget.innerHTML = this.files
.map((f) => `<span class="chip">${f.name}</span>`)
.join('');
this.submitBtnTarget.textContent = has ? 'Oblicz zestawienie' : 'Wybierz pliki';
}
setLoading(on) {
this.submitBtnTarget.disabled = on;
this.submitBtnTarget.textContent = on
? 'Obliczanie…'
: (this.files.length ? 'Oblicz zestawienie' : 'Wybierz pliki');
}
showError(msg) {
this.errorTarget.textContent = msg;
this.errorTarget.hidden = false;
}
hideError() {
this.errorTarget.hidden = true;
}
}