diff --git a/docs/mockup_admin.html b/docs/mockup_admin.html index bebc5e1..f209c77 100644 --- a/docs/mockup_admin.html +++ b/docs/mockup_admin.html @@ -74,7 +74,89 @@ window._MGR_REQUESTS = window._MGR_REQUESTS || [ {id:'r4', mgr:'Анна К.', color:'#7C3AED', type:'supply', prio:'normal', title:'Каталоги кухонь Hettich закончились', body:'Остался 1 экземпляр. Клиенты берут домой, не возвращают. Надо заказать 10 шт.', created:'вчера 17:22', status:'done'}, {id:'r5', mgr:'Мария С.', color:'#0891B2', type:'schedule', prio:'normal', title:'Запрос на замену смены — 31 мая', body:'Прошу разрешить обменяться сменой с Петром: я работаю 31 мая вместо него, он — 1 июня вместо меня.', created:'вчера 14:10', status:'new'}, ]; -window._staffSubTab = window._staffSubTab || 'schedule'; +window._staffSubTab = window._staffSubTab || 'chess'; + +// ── ДАННЫЕ: ШАХМАТКА (расписание менеджеров × слоты) ───────────────────────── +var _CHESS_HOURS = ['10:00','11:00','12:00','13:00','14:00','15:00','16:00','17:00','18:00','19:00','20:00']; +var _CHESS_MGRS = [ + {id:'ak', name:'Анна К.', short:'АК', color:'#7C3AED'}, + {id:'ms', name:'Мария С.', short:'МС', color:'#0891B2'}, + {id:'pv', name:'Пётр В.', short:'ПВ', color:'#059669'}, + {id:'iv', name:'Иван В.', short:'ИВ', color:'#D97706'}, +]; +// ячейка: {client, type, status} status: free|busy|done|noshow +// type: consult|measure|follow|tech +var _CHESS_DATA = { + 'ak':{'10:00':{client:'Орлова М.', type:'consult', status:'done'}, + '11:00':{client:'Соколов А.', type:'follow', status:'done'}, + '12:00':{client:'', type:'', status:'free'}, + '13:00':{client:'', type:'', status:'free'}, + '14:00':{client:'Ким Л.', type:'consult', status:'busy'}, + '15:00':{client:'Ким Л.', type:'consult', status:'busy'}, + '16:00':{client:'Захаров П.', type:'measure', status:'busy'}, + '17:00':{client:'Новикова С.', type:'consult', status:'free'}, + '18:00':{client:'', type:'', status:'free'}, + '19:00':{client:'Громов И.', type:'follow', status:'free'}, + '20:00':{client:'', type:'', status:'free'}}, + 'ms':{'10:00':{client:'Козлов Р.', type:'follow', status:'done'}, + '11:00':{client:'', type:'', status:'free'}, + '12:00':{client:'Лебедев С.', type:'consult', status:'done'}, + '13:00':{client:'', type:'', status:'free'}, + '14:00':{client:'Петрова А.', type:'tech', status:'busy'}, + '15:00':{client:'Петрова А.', type:'tech', status:'busy'}, + '16:00':{client:'', type:'', status:'free'}, + '17:00':{client:'Морозов В.', type:'consult', status:'busy'}, + '18:00':{client:'', type:'', status:'free'}, + '19:00':{client:'', type:'', status:'free'}, + '20:00':{client:'', type:'', status:'free'}}, + 'pv':{'10:00':{client:'', type:'', status:'free'}, + '11:00':{client:'Сидорова Н.', type:'consult', status:'done'}, + '12:00':{client:'Фёдоров К.', type:'follow', status:'noshow'}, + '13:00':{client:'', type:'', status:'free'}, + '14:00':{client:'', type:'', status:'free'}, + '15:00':{client:'Баринова Т.', type:'consult', status:'busy'}, + '16:00':{client:'Баринова Т.', type:'consult', status:'busy'}, + '17:00':{client:'', type:'', status:'free'}, + '18:00':{client:'Яковлев М.', type:'measure', status:'busy'}, + '19:00':{client:'Яковлев М.', type:'measure', status:'busy'}, + '20:00':{client:'', type:'', status:'free'}}, + 'iv':{'10:00':{client:'Тихонова Р.', type:'consult', status:'done'}, + '11:00':{client:'Тихонова Р.', type:'consult', status:'done'}, + '12:00':{client:'', type:'', status:'free'}, + '13:00':{client:'Волков Е.', type:'follow', status:'done'}, + '14:00':{client:'', type:'', status:'free'}, + '15:00':{client:'Кузьмин О.', type:'consult', status:'busy'}, + '16:00':{client:'', type:'', status:'free'}, + '17:00':{client:'Рыбаков Д.', type:'tech', status:'free'}, + '18:00':{client:'Рыбаков Д.', type:'tech', status:'free'}, + '19:00':{client:'', type:'', status:'free'}, + '20:00':{client:'', type:'', status:'free'}}, +}; + +// ── ДАННЫЕ: ИТОГИ ПО МЕНЕДЖЕРАМ (по месяцам) ────────────────────────────── +var _MONTHLY_STATS = [ + {id:'ak', name:'Анна К.', color:'#7C3AED', months:{ + 'Май':{visits:42, deals:14, revenue:847000, conversion:33, avg:60500, rating:4.8}, + 'Апр':{visits:38, deals:11, revenue:712000, conversion:29, avg:64700, rating:4.7}, + 'Мар':{visits:45, deals:16, revenue:920000, conversion:36, avg:57500, rating:4.9}, + }}, + {id:'ms', name:'Мария С.', color:'#0891B2', months:{ + 'Май':{visits:35, deals:9, revenue:610000, conversion:26, avg:67800, rating:4.5}, + 'Апр':{visits:41, deals:13, revenue:780000, conversion:32, avg:60000, rating:4.6}, + 'Мар':{visits:39, deals:12, revenue:695000, conversion:31, avg:57900, rating:4.4}, + }}, + {id:'pv', name:'Пётр В.', color:'#059669', months:{ + 'Май':{visits:28, deals:7, revenue:490000, conversion:25, avg:70000, rating:4.3}, + 'Апр':{visits:32, deals:9, revenue:540000, conversion:28, avg:60000, rating:4.2}, + 'Мар':{visits:30, deals:8, revenue:520000, conversion:27, avg:65000, rating:4.4}, + }}, + {id:'iv', name:'Иван В.', color:'#D97706', months:{ + 'Май':{visits:31, deals:8, revenue:530000, conversion:26, avg:66250, rating:4.1}, + 'Апр':{visits:29, deals:7, revenue:480000, conversion:24, avg:68600, rating:4.0}, + 'Мар':{visits:33, deals:10, revenue:610000, conversion:30, avg:61000, rating:4.3}, + }}, +]; +window._monthlyPeriod = window._monthlyPeriod || 'Май'; // ── СОГЛАСОВАНИЕ СМЕН: запросы ───────────────────────────────────────────── window._SHIFT_REQS = window._SHIFT_REQS || [ @@ -424,6 +506,29 @@ function _screenHome(){ +''; } + // ── Менеджеры сейчас ── + var mgrNowHtml = '
' + +'
👥 Менеджеры сейчас
' + +'
' + +_CHESS_MGRS.map(function(mgr){ + var rd=_CHESS_DATA[mgr.id]||{}; + var curSlot=rd['15:00']||{}; + var nextSlot=rd['16:00']||{}; + var statusText=curSlot.client?'С клиентом: '+curSlot.client:'Свободен'; + var statusColor=curSlot.client?'var(--success)':'var(--muted)'; + var nextText=nextSlot.client?'→ '+nextSlot.client:'→ Свободен'; + return '
' + +'
'+mgr.short+'
' + +'
' + +'
'+mgr.name+'
' + +'
'+statusText+'
' + +'
' + +'
'+nextText+'
' + +'
'; + }).join('') + +'
🔲 Открыть шахматку →
' + +'
'; + // ── Быстрые действия ── var quickHtml = '
' +'' @@ -432,13 +537,14 @@ function _screenHome(){ return '
' +'
' - +'
Чт, 22 мая 2026
' + +'
Чт, 29 мая 2026
' +'
Добрый день, Анна 👋
' +'
Салон Ленина · Администратор
' +'
' +kpiHtml +barHtml +alertsHtml + +mgrNowHtml +quickHtml +'
'; } @@ -1083,14 +1189,24 @@ function _screenStaff(){ var sub = window._staffSubTab || 'schedule'; var mgrNew = (window._MGR_REQUESTS||[]).filter(function(r){return r.status==='new';}).length; var shiftNew = (window._SHIFT_REQS||[]).filter(function(r){return r.status==='pending';}).length; - var chipBar = '
' - +'
📅 График
' - +'
' - +'📋 Заявки' - +(mgrNew+shiftNew>0?''+(mgrNew+shiftNew)+'':'') - +'
' + var _tabs=[ + {key:'chess', label:'🔲 Шахматка'}, + {key:'schedule', label:'📅 График'}, + {key:'requests', label:'📋 Заявки', badge: mgrNew+shiftNew}, + {key:'monthly', label:'📊 Итоги'}, + ]; + var chipBar = '
' + +_tabs.map(function(t){ + var act=sub===t.key; + return '
' + +t.label + +(t.badge>0?''+t.badge+'':'') + +'
'; + }).join('') +'
'; if(sub==='requests') return '
'+chipBar+_screenRequests()+'
'; + if(sub==='chess') return '
'+chipBar+_screenChess()+'
'; + if(sub==='monthly') return '
'+chipBar+_screenMonthly()+'
'; var edit = window._staffEditMode; @@ -1496,6 +1612,142 @@ function _cancelCheck(){ _nav('inventory'); } +// ── ШАХМАТКА ────────────────────────────────────────────────────────────────── +function _screenChess(){ + var typeColor={consult:'#3B82F6',measure:'#8B5CF6',follow:'#059669',tech:'#F59E0B'}; + var typeLabel={consult:'Консульт.',measure:'Замер',follow:'Повторный',tech:'Тех.вопрос'}; + var statusBg={free:'transparent',busy:'',done:'',noshow:'rgba(239,68,68,.12)'}; + var now = 15; // текущий час для демо + + // Текущий час-индикатор + var nowIdx = _CHESS_HOURS.indexOf('15:00'); + + var CELL_W = 68; // px ширина ячейки + var NAME_W = 40; // px ширина имени менеджера + + // Шапка часов + var headerRow = '
' + +'
Менеджер
' + +_CHESS_HOURS.map(function(h,i){ + var isCur=i===nowIdx; + return '
'+h+'
'; + }).join('') + +'
'; + + // Строки менеджеров + var rows = _CHESS_MGRS.map(function(mgr){ + var rowData = _CHESS_DATA[mgr.id]||{}; + return '
' + +'
' + +'
'+mgr.short+'
' + +'
' + +_CHESS_HOURS.map(function(h,i){ + var cell=rowData[h]||{status:'free'}; + var isCur=i===nowIdx; + var bg=cell.status==='done'?'rgba(16,185,129,.1)':cell.status==='busy'?'rgba(59,130,246,.1)':cell.status==='noshow'?'rgba(239,68,68,.1)':''; + var brd=cell.status==='done'?'1px solid rgba(16,185,129,.25)':cell.status==='busy'?'1px solid rgba(59,130,246,.25)':cell.status==='noshow'?'1px solid rgba(239,68,68,.2)':'1px solid rgba(0,0,0,.05)'; + var txt=cell.status==='done'?'var(--success)':cell.status==='busy'?'#1D4ED8':cell.status==='noshow'?'var(--danger)':'var(--muted)'; + var icon=cell.status==='done'?'✓':cell.status==='noshow'?'✗':cell.status==='busy'?'●':''; + return '
' + +(cell.client + ?'
'+icon+' '+cell.client+'
' + +'
'+typeLabel[cell.type]+'
' + :'
') + +'
'; + }).join('') + +'
'; + }).join(''); + + // Легенда + var legend='
' + +'✓ Завершено' + +'● Занято' + +'✗ Не пришёл' + +'— Свободно' + +'
'; + + // Итог строки: занятость + var summary='
' + +'
ЗАНЯТОСТЬ СЕГОДНЯ
' + +'
' + +_CHESS_MGRS.map(function(mgr){ + var rd=_CHESS_DATA[mgr.id]||{}; + var total=_CHESS_HOURS.length; + var busy=_CHESS_HOURS.filter(function(h){return (rd[h]||{}).client;}).length; + var pct=Math.round(busy/total*100); + var col=pct>=70?'var(--success)':pct>=40?'var(--warn)':'var(--muted)'; + return '
' + +'
'+mgr.short+'
' + +'
' + +'
'+pct+'%
' + +'
'+busy+'/'+total+'сл
' + +'
'; + }).join('') + +'
'; + + return '
' + +'
' + +headerRow+rows + +'
' + +legend+summary; +} + +// ── ПОМЕСЯЧНЫЕ ИТОГИ ─────────────────────────────────────────────────────────── +function _screenMonthly(){ + var months=['Май','Апр','Мар']; + var per=window._monthlyPeriod||'Май'; + + var periodTabs='
' + +months.map(function(m){ + var act=m===per; + return '
'+m+'
'; + }).join('') + +'
'; + + // Топ-менеджер + var sorted=_MONTHLY_STATS.slice().sort(function(a,b){return (b.months[per]||{revenue:0}).revenue-(a.months[per]||{revenue:0}).revenue;}); + var top=sorted[0]; + + var topCard='
' + +'
🏆 Лидер месяца · '+per+'
' + +'
' + +'
'+top.name.split(' ').map(function(w){return w[0];}).join('')+'
' + +'
'+top.name+'
' + +'
'+_fmtMoney((top.months[per]||{revenue:0}).revenue)+' · '+((top.months[per]||{conversion:0}).conversion)+'% конверсия
' + +'
'; + + var cards=sorted.map(function(mgr,idx){ + var s=mgr.months[per]||{}; + var prev=mgr.months[months[1]]||{}; + var revDelta=s.revenue&&prev.revenue?Math.round((s.revenue-prev.revenue)/prev.revenue*100):0; + var convDelta=s.conversion&&prev.conversion?s.conversion-prev.conversion:0; + return '
' + +'
' + +'
'+mgr.name.split(' ').map(function(w){return w[0];}).join('')+'
' + +'
'+mgr.name+'
' + +'
Рейтинг: ★ '+s.rating+'
' + +'
#'+(idx+1)+'
' + +'
' + // Метрики 2×2 + +'
' + +[ + {label:'Выручка', val:_fmtMoney(s.revenue||0), delta:revDelta+'%', up:revDelta>=0}, + {label:'Конверсия', val:(s.conversion||0)+'%', delta:(convDelta>=0?'+':'')+convDelta+'%', up:convDelta>=0}, + {label:'Визиты', val:(s.visits||0)+' кл.', delta:'', up:true}, + {label:'Сделки', val:(s.deals||0)+' шт.', delta:'ср. '+_fmtMoney(s.avg||0), up:true}, + ].map(function(m){ + return '
' + +'
'+m.label+'
' + +'
'+m.val+'
' + +(m.delta?'
'+m.delta+'
':'') + +'
'; + }).join('') + +'
'; + }).join(''); + + return periodTabs+topCard+cards; +} + // ── ЗАЯВКИ МЕНЕДЖЕРОВ ───────────────────────────────────────────────────────── function _screenRequests(){ var filter = window._reqFilter || 'all';