К
КапиталМастера
Финансы · Клиенты · Блог
Нет аккаунта? Зарегистрироваться
🔒 Данные зашифрованы AES-256 · только ваш браузер
М
Мастер
Творческий предприниматель
0
Операций
0
Клиентов
0 ₽
Баланс
Инструкция
М
База контактов
Клиенты и партнёры
◆ Финансы
🔍
Планирование
Ваш Календарь
◆ Финансы
События сегодня
Мои работы и посты
Мой Блог
◆ Финансы
Финансовый обзор
Добрый день, Мастер
Enter → доход Shift+Enter → расход
Новая операция
Ближайшие записи
Последние операции
Управление
Ваш Капитал
Правило распределения
50 / 30 / 20
■ Бизнес■ Личное■ Капитал
Путь к финансовой свободе
1
Подушка безопасности
3–6 месяцев расходов на отдельном счёте
2
Инвестиционный портфель
10% дохода ежемесячно в диверсифицированные активы
3
Финансовая свобода
Пассивный доход превышает расходы
Организация
Статьи доходов и расходов
Создать статью
Личный кабинет
Ваш Профиль
◆ Финансы

Резервная копия

Ещё не создавалась

↑ Перетащите .cmb для восстановления

или нажмите для выбора

Быстрый ввод
`); 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=>`
${p.caption||''}
`).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)}
Расход
${fmt(totExp)}
Баланс
${fmt(bal)}
Клиентов
${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}
Операций
${fmt(inc)}
Доход ₽
${fmt(exp)}
Расход ₽
${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 ─── */