implemented step 07

- added categories for 1. step in wizard
This commit is contained in:
2026-06-12 19:01:34 +02:00
parent b4960c4e39
commit 0e0670574d
6 changed files with 388 additions and 9 deletions

View File

@ -7,7 +7,13 @@ const App = {
userId: localStorage.getItem('ww_user_id'),
currentStep: 1,
totalSteps: 8,
project: null
project: null,
categories: [],
selection: {
category: null,
subcategory: null,
customDescription: ''
}
},
async init() {
@ -17,10 +23,54 @@ const App = {
await this.initSession();
}
await this.loadCategories();
this.bindEvents();
// If we don't have a project, try to load existing or create one
if (!this.state.project) {
await this.loadLastProject();
}
this.showStep(this.state.currentStep);
},
async loadLastProject() {
try {
const response = await this.apiCall('listProjects');
if (response.success && response.data.length > 0) {
// Load the most recent project
const lastProject = response.data[0];
const statusResponse = await this.apiCall('getProjectStatus', {}, lastProject.project_id);
if (statusResponse.success) {
this.state.project = statusResponse.data;
this.state.currentStep = this.state.project.current_step || 1;
console.log('Loaded existing project:', this.state.project.project_id);
this.syncSelectionWithProject();
}
} else {
await this.createProject();
}
} catch (error) {
console.error('Failed to load projects:', error);
await this.createProject();
}
},
syncSelectionWithProject() {
if (this.state.project && this.state.project.wizard_data.business_category) {
const bc = this.state.project.wizard_data.business_category;
this.state.selection.category = bc.group;
this.state.selection.subcategory = bc.subcategory;
this.state.selection.customDescription = bc.custom_description || '';
if (this.state.selection.category) {
this.selectCategory(this.state.selection.category);
this.state.selection.subcategory = bc.subcategory; // restore after selectCategory resets it
this.renderSubcategories(this.state.selection.category);
}
}
},
async initSession() {
try {
const response = await this.apiCall('initSession');
@ -31,14 +81,38 @@ const App = {
}
} catch (error) {
console.error('Failed to initialize session:', error);
alert('Chyba pri inicializácii session. Skontrolujte pripojenie.');
alert('Chyba pri inicializácii session.');
}
},
async createProject() {
try {
const response = await this.apiCall('createProject');
if (response.success) {
this.state.project = response.data;
console.log('Project created:', this.state.project.project_id);
}
} catch (error) {
console.error('Failed to create project:', error);
}
},
async loadCategories() {
try {
const response = await this.apiCall('getCategories');
if (response.success) {
this.state.categories = response.data.categories;
this.renderCategories();
}
} catch (error) {
console.error('Failed to load categories:', error);
}
},
async apiCall(action, payload = {}, projectId = null) {
const body = {
action,
project_id: projectId,
project_id: projectId || (this.state.project ? this.state.project.project_id : null),
payload
};
@ -67,6 +141,75 @@ const App = {
bindEvents() {
document.getElementById('btn-next').addEventListener('click', () => this.nextStep());
document.getElementById('btn-prev').addEventListener('click', () => this.prevStep());
document.getElementById('custom-description').addEventListener('input', (e) => {
this.state.selection.customDescription = e.target.value;
});
},
renderCategories() {
const container = document.getElementById('category-list');
container.innerHTML = '';
const icons = {
gastro: '🍕',
beauty: '✨',
crafts: '🛠️',
professional: '💼',
other: '❓'
};
this.state.categories.forEach(cat => {
const card = document.createElement('div');
card.className = 'category-card';
if (this.state.selection.category === cat.id) card.classList.add('selected');
card.innerHTML = `
<div class="category-icon">${icons[cat.id] || '📁'}</div>
<div class="category-name">${cat.name}</div>
`;
card.addEventListener('click', () => this.selectCategory(cat.id));
container.appendChild(card);
});
},
selectCategory(categoryId) {
this.state.selection.category = categoryId;
this.state.selection.subcategory = null;
this.renderCategories();
this.renderSubcategories(categoryId);
document.getElementById('subcategory-container').classList.remove('hidden');
if (categoryId === 'other') {
document.getElementById('custom-category-group').classList.remove('hidden');
} else {
document.getElementById('custom-category-group').classList.add('hidden');
}
},
renderSubcategories(categoryId) {
const container = document.getElementById('subcategory-list');
container.innerHTML = '';
const category = this.state.categories.find(c => c.id === categoryId);
if (!category) return;
category.subcategories.forEach(sub => {
const chip = document.createElement('div');
chip.className = 'chip';
if (this.state.selection.subcategory === sub.id) chip.classList.add('selected');
chip.textContent = sub.name;
chip.addEventListener('click', () => {
this.state.selection.subcategory = sub.id;
this.renderSubcategories(categoryId);
});
container.appendChild(chip);
});
},
showStep(n) {
@ -82,7 +225,31 @@ const App = {
this.updateUI();
},
nextStep() {
async nextStep() {
if (this.state.currentStep === 1) {
if (!this.state.selection.category || !this.state.selection.subcategory) {
alert('Prosím, vyberte kategóriu aj podkategóriu.');
return;
}
try {
await this.apiCall('saveStep', {
step: 1,
data: {
business_category: {
group: this.state.selection.category,
subcategory: this.state.selection.subcategory,
custom_description: this.state.selection.category === 'other' ? this.state.selection.customDescription : null
}
}
});
} catch (error) {
console.error('Save step failed:', error);
alert('Nepodarilo sa uložiť dáta.');
return;
}
}
if (this.state.currentStep < this.state.totalSteps) {
this.showStep(this.state.currentStep + 1);
}
@ -95,7 +262,6 @@ const App = {
},
updateUI() {
// Update buttons
const btnPrev = document.getElementById('btn-prev');
const btnNext = document.getElementById('btn-next');
@ -107,7 +273,6 @@ const App = {
btnNext.textContent = 'Pokračovať';
}
// Update progress bar
const progressFill = document.querySelector('.progress-fill');
const percent = ((this.state.currentStep - 1) / (this.state.totalSteps - 1)) * 100;
progressFill.style.width = `${percent}%`;