`);
document.getElementById('mc')?.addEventListener('click',hideModal);
let selStart='',selEnd='',selSvc='';
document.querySelectorAll('.service-chip').forEach(ch=>{ ch.addEventListener('click',()=>{ document.querySelectorAll('.service-chip').forEach(x=>x.classList.remove('selected')); ch.classList.add('selected'); selSvc=ch.dataset.svc; document.getElementById('me-title').value=selSvc; }); });
document.querySelectorAll('[data-ts]').forEach(el=>{ el.addEventListener('click',()=>{ document.querySelectorAll('[data-ts]').forEach(x=>x.classList.remove('selected')); el.classList.add('selected'); selStart=el.dataset.ts; }); });
document.querySelectorAll('[data-te]').forEach(el=>{ el.addEventListener('click',()=>{ document.querySelectorAll('[data-te]').forEach(x=>x.classList.remove('selected')); el.classList.add('selected'); selEnd=el.dataset.te; }); });
document.getElementById('me-save')?.addEventListener('click',()=>{
const title=document.getElementById('me-title').value.trim()||selSvc;
if(!title) return alert2('Введите название','error');
const amount=parseFloat(document.getElementById('me-amount').value)||null;
const clientId=document.getElementById('me-client').value||null;
const ev={id:uid(),title,date:document.getElementById('me-date').value,startTime:selStart,endTime:selEnd,clientId,service:selSvc,amount,description:document.getElementById('me-desc').value.trim()};
if(!db.events) db.events=[];
db.events.push(ev);
if(amount&&clientId){
const incCat=db.categories.find(c=>c.type==='income'&&c.financeType==='business');
db.transactions.push({id:uid(),type:'income',financeType:'business',amount,categoryId:incCat?.id||null,description:title,clientId,date:new Date(ev.date).toISOString(),createdAt:new Date().toISOString()});
const cl=db.clients.find(c=>c.id===clientId);
if(cl){ if(!cl.interactions) cl.interactions=[]; cl.interactions.push({date:ev.date,description:title,amount}); }
}
saveDb(); hideModal(); renderCalendar(); alert2('Запись добавлена ✓');
});
}
/* ─── Portfolio ─── */
const PORT_CATS=[{id:'beauty',label:'💄 Бьюти'},{id:'photo',label:'📸 Фото'},{id:'fashion',label:'👗 Мода'},{id:'before_after',label:'✨ До/После'},{id:'other',label:'🎨 Разное'}];
function renderPortfolio(){
const db=window.__CM.db;
const pg=document.getElementById('portfolio-cats');
const port=db.portfolio||[];
if(port.length===0){ pg.innerHTML='
Нет работ. Добавьте первое фото!
'; return; }
pg.innerHTML=PORT_CATS.map(cat=>{ const items=port.filter(p=>p.category===cat.id); if(items.length===0) return ''; return `
${cat.label}
${items.map(p=>`

`).join('')}
`; }).join('');
pg.querySelectorAll('[data-del-port]').forEach(b=>{ b.addEventListener('click',()=>{ if(confirm('Удалить?')){ db.portfolio=db.portfolio.filter(p=>p.id!==b.dataset.delPort); saveDb(); renderPortfolio(); } }); });
}
/* ─── Dashboard ─── */
function renderDashboard(){
const cu=window.__CM.cu, db=window.__CM.db;
const tx=db.transactions;
const bInc=tx.filter(t=>t.type==='income'&&t.financeType==='business').reduce((s,t)=>s+(+t.amount||0),0);
const pInc=tx.filter(t=>t.type==='income'&&t.financeType==='personal').reduce((s,t)=>s+(+t.amount||0),0);
const totExp=tx.filter(t=>t.type==='expense').reduce((s,t)=>s+(+t.amount||0),0);
const totInc=bInc+pInc, bal=totInc-totExp;
document.getElementById('dash-name').textContent=cu?.displayName||'Мастер';
// Update sidebar balance badge
const balBadge=document.getElementById('nb-balance');
if(balBadge) balBadge.textContent=(bal>=0?'+':'')+fmt(bal)+' ₽';
document.getElementById('dash-metrics').innerHTML=`
Общий доход
${fmt(totInc)} ₽
Клиентов
${db.clients.length}
`;
const qcat=document.getElementById('q-cat');
qcat.innerHTML='
'+db.categories.map(c=>`
`).join('');
const today=new Date().toISOString().slice(0,10);
const upEv=(db.events||[]).filter(e=>e.date>=today).sort((a,b)=>a.date.localeCompare(b.date)).slice(0,4);
const de=document.getElementById('dash-events');
if(upEv.length===0){ de.innerHTML='
Нет предстоящих записей
'; }
else{ de.innerHTML=upEv.map(e=>{ const cl=e.clientId?db.clients.find(c=>c.id===e.clientId):null; return `
${e.startTime||'—'}${e.endTime?'\n→ '+e.endTime:''}
${e.title}
${cl?`
👤 ${cl.name}
`:''}
${new Date(e.date+'T12:00').toLocaleDateString('ru-RU',{day:'numeric',month:'short'})}
`; }).join(''); }
const dtx=document.getElementById('dash-tx');
const recent=tx.slice(-8).reverse();
if(recent.length===0){ dtx.innerHTML='
Нет операций
'; return; }
dtx.innerHTML=recent.map(t=>{ const cat=db.categories.find(c=>c.id===t.categoryId)||{name:'Без категории',color:'#B8BDC8'}; const isInc=t.type==='income'; return `
${cat.name}${t.financeType==='business'?'БИЗ':'ЛИЧ'}
${t.description||''}${t.description?' · ':''} ${new Date(t.createdAt||t.date).toLocaleDateString('ru-RU')}
${isInc?'+':'−'}${fmt(t.amount)} ₽
`; }).join('');
dtx.querySelectorAll('[data-del-tx]').forEach(b=>{ b.addEventListener('click',()=>{ if(confirm('Удалить?')){ db.transactions=db.transactions.filter(t=>t.id!==b.dataset.delTx); saveDb(); renderDashboard(); } }); });
}
/* ─── Capital ─── */
function renderCapital(){
const db=window.__CM.db;
const tx=db.transactions;
const bInc=tx.filter(t=>t.type==='income'&&t.financeType==='business').reduce((s,t)=>s+(+t.amount||0),0);
const pInc=tx.filter(t=>t.type==='income'&&t.financeType==='personal').reduce((s,t)=>s+(+t.amount||0),0);
const tot=bInc+pInc;
const rule=db.settings?.splitRule||'50/30/20';
const [bp,pp,cp]=rule.split('/').map(Number);
document.getElementById('cap-rule').value=rule;
document.getElementById('cap-rule-display').textContent=rule.split('/').join(' / ');
document.getElementById('sp-biz').style.width=bp+'%'; document.getElementById('sp-per').style.width=pp+'%'; document.getElementById('sp-cap').style.width=cp+'%';
const tBiz=Math.round(tot*bp/100),tPer=Math.round(tot*pp/100),tCap=Math.round(tot*cp/100);
document.getElementById('cap-progress-card').innerHTML=`
🏢 Бизнес (${bp}%) — цель ${fmt(tBiz)} ₽${fmt(bInc)} ₽
🏠 Личное (${pp}%) — цель ${fmt(tPer)} ₽${fmt(pInc)} ₽
📈 Капитал (${cp}%) — цель ${fmt(tCap)} ₽—
`;
}
/* ─── Categories ─── */
function renderCategories(){
const db=window.__CM.db;
const cl=document.getElementById('cat-list');
if(db.categories.length===0){ cl.innerHTML='
Нет статей — создайте первую!
'; return; }
cl.innerHTML=db.categories.map(c=>`
${c.name}
${c.type==='income'?'Доход':'Расход'} · ${c.financeType==='business'?'Бизнес':'Личное'}
`).join('');
cl.querySelectorAll('[data-del-cat]').forEach(b=>{ b.addEventListener('click',()=>{ if(confirm('Удалить статью?')){ db.categories=db.categories.filter(c=>c.id!==b.dataset.delCat); saveDb(); renderCategories(); } }); });
}
/* ─── Wisdom ─── */
/* ─── Profile ─── */
function renderProfile(){
const cu=window.__CM.cu, db=window.__CM.db;
const nm=cu?.displayName||'Мастер';
const init=nm.split(' ').map(n=>n[0]).join('').toUpperCase().slice(0,2)||'М';
document.getElementById('profile-header').innerHTML=`
${init}
${nm}
${cu?.specialty||'Творческий предприниматель'}
`;
document.getElementById('p-name').value=cu?.displayName||'';
document.getElementById('p-spec').value=cu?.specialty||'';
document.getElementById('p-email').value=cu?.email||'';
document.getElementById('p-avatar').value=cu?.avatarUrl||'';
document.getElementById('p-services').value=cu?.services||db.settings?.services||'';
const inc=db.transactions.filter(t=>t.type==='income').reduce((s,t)=>s+(+t.amount||0),0);
const exp=db.transactions.filter(t=>t.type==='expense').reduce((s,t)=>s+(+t.amount||0),0);
document.getElementById('profile-stats').innerHTML=`
${db.transactions.length}
Операций
${db.clients.length}
Клиентов
`;
const bk=localStorage.getItem(BK_KEY);
document.getElementById('backup-date-lbl').textContent=bk?'Последняя копия: '+new Date(bk).toLocaleDateString('ru-RU'):'Ещё не создавалась';
}
/* ─── Export / Import ─── */
function exportData(){
const cu=window.__CM.cu, db=window.__CM.db;
const pw=sessionStorage.getItem(SP_KEY); if(!pw) return;
const ex={version:'7.0',at:new Date().toISOString(),user:{id:cu.id,phone:cu.phone,displayName:cu.displayName,specialty:cu.specialty||'',email:cu.email||'',services:cu.services||''},data:db};
const blob=new Blob([enc(ex,pw)],{type:'application/octet-stream'});
const url=URL.createObjectURL(blob);
const a=document.createElement('a'); a.href=url; a.download=`capital-master-${new Date().toISOString().slice(0,10)}.cmb`;
document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url);
localStorage.setItem(BK_KEY,new Date().toISOString()); alert2('Резервная копия сохранена ✓'); renderProfile();
}
function importData(file){
const pw=sessionStorage.getItem(SP_KEY); if(!pw) return;
const r=new FileReader();
r.onload=function(e){
try{
let obj=dec(e.target.result,pw);
if(!obj){ const op=prompt('Введите пароль от файла:'); if(!op) return; obj=dec(e.target.result,op); }
if(!obj?.data){ alert2('Неверный формат','error'); return; }
if(!confirm('Заменить текущие данные?')) return;
window.__CM.db=obj.data;
const db=window.__CM.db;
if(!db.events) db.events=[]; if(!db.settings) db.settings={splitRule:'50/30/20',services:''}; if(!db.portfolio) db.portfolio=[];
if(obj.user?.displayName) updateUser({displayName:obj.user.displayName,specialty:obj.user.specialty||'',email:obj.user.email||'',services:obj.user.services||''});
saveDb(); renderProfile(); renderClients(); alert2('Данные восстановлены ✓');
}catch(err){ alert2('Ошибка: '+err.message,'error'); }
};
r.readAsText(file);
}
function showAddCatModal(){
showModal(`
Новая статья
`);
document.getElementById('mc2')?.addEventListener('click',hideModal);
document.getElementById('mc-save')?.addEventListener('click',()=>{
const db=window.__CM.db;
const name=document.getElementById('mc-name').value.trim();
if(!name) return alert2('Введите название','error');
db.categories.push({id:uid(),name,type:document.getElementById('mc-type').value,financeType:document.getElementById('mc-fin').value,color:document.getElementById('mc-color').value});
saveDb(); hideModal(); renderCategories();
const qcat=document.getElementById('q-cat');
if(qcat) qcat.innerHTML='
'+db.categories.map(c=>`
`).join('');
alert2('Статья создана ✓');
});
}
function showAddPortfolio(){
showModal(`
Добавить работу в портфолио
`);
document.getElementById('mcp')?.addEventListener('click',hideModal);
document.getElementById('pp-save')?.addEventListener('click',()=>{
const db=window.__CM.db;
const url=document.getElementById('pp-url').value.trim();
if(!url) return alert2('Введите URL','error');
if(!db.portfolio) db.portfolio=[];
db.portfolio.push({id:uid(),url,category:document.getElementById('pp-cat').value,caption:document.getElementById('pp-caption').value.trim(),date:new Date().toISOString().slice(0,10)});
saveDb(); hideModal(); renderPortfolio(); alert2('Работа добавлена ✓');
});
}
/* ─── App Shell ─── */