mirror of
https://github.com/wasrusgen/wasrusgen1-crm.git
synced 2026-06-03 14:24:47 +00:00
feat(CRM): мобильный адаптив — гамбургер-меню, drawer-сайдбар, KPI/гриды в 1-2 колонки
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
11486ce8a8
commit
0a9d924d58
@ -130,12 +130,36 @@ body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);displ
|
||||
.spin{display:inline-block;animation:sp 1s linear infinite}@keyframes sp{to{transform:rotate(360deg)}}
|
||||
.empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:#cbd5e1;gap:10px;height:100%}
|
||||
::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-thumb{background:rgba(0,0,0,.12);border-radius:4px}
|
||||
/* ── Мобильный (CRM с телефона) ── */
|
||||
.hdr-burger{display:none;background:none;border:none;color:#fff;font-size:22px;cursor:pointer;padding:0 2px;line-height:1;flex-shrink:0}
|
||||
.sb-backdrop{display:none;position:fixed;inset:54px 0 0 0;background:rgba(0,0,0,.55);z-index:40}
|
||||
.sb-backdrop.show{display:block}
|
||||
@media(max-width:680px){
|
||||
.hdr{padding:0 12px;gap:8px}
|
||||
.hdr-burger{display:block}
|
||||
.sb{position:fixed;left:-260px;top:54px;bottom:0;z-index:50;width:240px;transition:left .25s ease;box-shadow:3px 0 18px rgba(0,0,0,.45)}
|
||||
.sb.open{left:0}
|
||||
.main{width:100%}
|
||||
.scroll{padding:14px}
|
||||
.kpis{grid-template-columns:1fr 1fr;gap:8px}
|
||||
.kpi{padding:11px 13px}
|
||||
.kpi-v{font-size:21px}
|
||||
.cc-grid{grid-template-columns:1fr 1fr}
|
||||
.deal-overview{grid-template-columns:1fr!important}
|
||||
.canvas-grid{grid-template-columns:1fr 1fr}
|
||||
.mtabs{flex-wrap:nowrap;overflow-x:auto}
|
||||
.mtab{min-width:auto;padding:9px 12px}
|
||||
.cc-top{flex-wrap:wrap}
|
||||
.cc-name{font-size:17px}
|
||||
.sec-h{font-size:14px}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="hdr"><div class="hdr-ic">@</div><div class="hdr-t">wasrusgen1<span class="hdr-sep"></span><b>КОНСАЛТИНГ</b></div><div class="hdr-badge">CRM</div><div class="hdr-r"><span style="width:8px;height:8px;border-radius:50%;background:var(--mid)"></span>Руслан</div></header>
|
||||
<header class="hdr"><button class="hdr-burger" onclick="toggleSb()" aria-label="Меню">☰</button><div class="hdr-ic">@</div><div class="hdr-t">wasrusgen1<span class="hdr-sep"></span><b>КОНСАЛТИНГ</b></div><div class="hdr-badge">CRM</div><div class="hdr-r"><span style="width:8px;height:8px;border-radius:50%;background:var(--mid)"></span>Руслан</div></header>
|
||||
<div class="layout">
|
||||
<aside class="sb">
|
||||
<div class="sb-backdrop" id="sbBackdrop" onclick="toggleSb()"></div>
|
||||
<aside class="sb" id="sbNav">
|
||||
<div class="sb-nav">
|
||||
<div class="nav-item active" id="nav-dash" onclick="setView('dashboard')"><span class="ic">📊</span> Дашборд</div>
|
||||
<div class="nav-item" id="nav-pipe" onclick="setView('pipeline')"><span class="ic">🎯</span> Воронка</div>
|
||||
@ -155,6 +179,9 @@ const pipeMap=Object.fromEntries(PIPE.map(p=>[p[0],p]));
|
||||
function esc(s){return (s||"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}
|
||||
function fmt(s){return esc(s).replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>")}
|
||||
function money(n){return (n||0).toLocaleString("ru-RU")+" ₽"}
|
||||
// ── Мобильное меню ──
|
||||
function toggleSb(){const sb=document.getElementById('sbNav'),bd=document.getElementById('sbBackdrop');const o=sb.classList.toggle('open');bd.classList.toggle('show',o);}
|
||||
function closeSb(){const sb=document.getElementById('sbNav'),bd=document.getElementById('sbBackdrop');if(sb)sb.classList.remove('open');if(bd)bd.classList.remove('show');}
|
||||
// ── UI-состояние: сворачивание секций + фильтры (запоминается) ──
|
||||
const ui=(()=>{try{return JSON.parse(localStorage.getItem('crm_ui'))||{}}catch(e){return{}}})();
|
||||
ui.collapsed=ui.collapsed||{revenue:true}; // динамика свёрнута по умолчанию
|
||||
@ -195,9 +222,9 @@ async function newClient(){
|
||||
await fetch(`${API}/api/project/profile`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:d.token,client_name:name,niche,description:""})});
|
||||
await loadProjects();openClient(d.token);
|
||||
}
|
||||
function setView(v){view=v;current=null;document.getElementById("nav-dash").classList.toggle("active",v==="dashboard");document.getElementById("nav-pipe").classList.toggle("active",v==="pipeline");renderClientList();render();}
|
||||
function setView(v){view=v;current=null;if(window.innerWidth<=680)closeSb();document.getElementById("nav-dash").classList.toggle("active",v==="dashboard");document.getElementById("nav-pipe").classList.toggle("active",v==="pipeline");renderClientList();render();}
|
||||
async function openClient(token){
|
||||
current=token;view="client";mainTab="deal";editPayIdx=-1;document.querySelectorAll(".nav-item").forEach(n=>n.classList.remove("active"));
|
||||
current=token;view="client";mainTab="deal";editPayIdx=-1;if(window.innerWidth<=680)closeSb();document.querySelectorAll(".nav-item").forEach(n=>n.classList.remove("active"));
|
||||
const r=await fetch(`${API}/api/project/${token}`);state=await r.json();renderClientList();render();syncPaymentReminders();
|
||||
}
|
||||
function render(){
|
||||
@ -384,7 +411,7 @@ function renderMainPanel(){
|
||||
<div class="cc-field" id="payStatusBox"></div>
|
||||
</div>
|
||||
<div class="cc-actions"><button class="btn btn-p" onclick="inviteLink()">🔗 Ссылка клиенту</button><button class="btn btn-p" style="background:#0088cc" onclick="inviteTelegram()">✈ В Telegram</button><a class="btn btn-g" href="cabinet.html?t=${current}" target="_blank">👁 Открыть кабинет</a><button class="btn btn-g" style="margin-left:auto;border-color:#FECACA;color:#DC2626" onclick="deleteClient()">🗑 Удалить</button></div>
|
||||
<div style="display:grid;grid-template-columns:1.35fr 1fr;gap:14px;align-items:start">
|
||||
<div class="deal-overview" style="display:grid;grid-template-columns:1.35fr 1fr;gap:14px;align-items:start">
|
||||
<div class="blk" style="margin:0">
|
||||
<div style="display:flex;align-items:center;margin-bottom:6px"><b style="font-size:13px">📍 Прогресс проекта</b><span style="margin-left:auto;font-size:11px;color:var(--muted)">${doneCnt}/5 этапов</span></div>
|
||||
${CLIENT_STAGES.map((s,i)=>{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user