mirror of
https://github.com/wasrusgen/wasrusgen1-crm.git
synced 2026-06-03 17:04:46 +00:00
913 lines
52 KiB
HTML
913 lines
52 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>@wasrusgen1 CRM — Клиент</title>
|
||
<style>
|
||
*{box-sizing:border-box;margin:0;padding:0}
|
||
body{background:#C8CACD;min-height:100vh;display:flex;flex-direction:column;align-items:center;padding:20px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif}
|
||
|
||
body[data-theme="zov"] {--accent:#003E7E;--accent2:#76BD22;--bg:#F5F6F8;--card:#FFFFFF;--ink:#1A1A2E;--muted:#8A94A6;--danger:#EF4444;--warn:#F59E0B;--success:#10B981}
|
||
body[data-theme="radar"] {--accent:#4338CA;--accent2:#6366F1;--bg:#F9FAFB;--card:#FFFFFF;--ink:#111827;--muted:#6B7280;--danger:#EF4444;--warn:#F59E0B;--success:#10B981}
|
||
body[data-theme="dark"] {--accent:#4338CA;--accent2:#6366F1;--bg:#111827;--card:#1F2937;--ink:#F9FAFB;--muted:#9CA3AF;--danger:#EF4444;--warn:#F59E0B;--success:#10B981}
|
||
|
||
#controls{display:flex;align-items:center;gap:12px;margin-bottom:16px;flex-wrap:wrap;justify-content:center;width:100%;max-width:600px}
|
||
#controls label{color:#fff;font-size:13px;font-weight:600}
|
||
#screenSelect{padding:8px 12px;border-radius:10px;border:none;background:#fff;font-size:13px;color:#333;cursor:pointer;min-width:220px;box-shadow:0 2px 8px rgba(0,0,0,.15)}
|
||
#themeButtons{display:flex;gap:6px}
|
||
.theme-btn{padding:7px 14px;border-radius:9px;border:2px solid transparent;font-size:12px;font-weight:700;cursor:pointer;transition:all .2s}
|
||
.theme-btn.active{border-color:#fff;transform:scale(1.05)}
|
||
.theme-btn[data-t="zov"] {background:#003E7E;color:#fff}
|
||
.theme-btn[data-t="radar"]{background:#4338CA;color:#fff}
|
||
.theme-btn[data-t="dark"] {background:#111827;color:#6366F1}
|
||
|
||
#phoneWrap{position:relative;width:390px;flex-shrink:0}
|
||
#phoneFrame{width:390px;height:844px;background:var(--bg);border-radius:44px;overflow:hidden;box-shadow:0 24px 80px rgba(0,0,0,.4),inset 0 0 0 1px rgba(255,255,255,.15);position:relative;display:flex;flex-direction:column}
|
||
#statusBar{height:44px;background:var(--card);display:flex;align-items:center;justify-content:space-between;padding:0 24px;flex-shrink:0;font-size:13px;font-weight:600;color:var(--ink);z-index:10}
|
||
.sb-right{display:flex;align-items:center;gap:6px}
|
||
#screen{flex:1;overflow-y:auto;overflow-x:hidden;position:relative;scrollbar-width:none;background:var(--bg)}
|
||
#screen::-webkit-scrollbar{display:none}
|
||
|
||
.bottom-nav{height:60px;background:rgba(255,255,255,.92);backdrop-filter:blur(12px);border-top:1px solid rgba(0,0,0,.06);display:flex;align-items:center;justify-content:space-around;flex-shrink:0;position:relative;z-index:100}
|
||
.nav-item{display:flex;flex-direction:column;align-items:center;gap:2px;cursor:pointer;padding:6px 10px;border-radius:10px;transition:all .15s;flex:1}
|
||
.nav-item svg{width:22px;height:22px;color:var(--muted)}
|
||
.nav-item span{font-size:10px;color:var(--muted);font-weight:500}
|
||
.nav-item.active svg{color:var(--accent)}
|
||
.nav-item.active span{color:var(--accent)}
|
||
|
||
.page{padding:0 0 80px;min-height:100%}
|
||
.page-header{display:flex;align-items:center;gap:12px;padding:16px 16px 12px;background:var(--card);border-bottom:1px solid rgba(0,0,0,.06);position:sticky;top:0;z-index:50}
|
||
.page-header h2{font-size:17px;font-weight:700;color:var(--ink);flex:1}
|
||
.back-btn{width:32px;height:32px;border-radius:50%;background:var(--bg);display:flex;align-items:center;justify-content:center;cursor:pointer;border:none;flex-shrink:0}
|
||
.back-btn svg{color:var(--accent);width:18px;height:18px}
|
||
.header-action{width:36px;height:36px;border-radius:50%;background:var(--bg);display:flex;align-items:center;justify-content:center;cursor:pointer;border:none}
|
||
.header-action svg{color:var(--accent);width:20px;height:20px}
|
||
|
||
.card{background:var(--card);border-radius:16px;box-shadow:0 2px 12px rgba(0,0,0,.07);padding:16px;margin-bottom:12px}
|
||
.card.warn-border{border-left:3px solid var(--warn)}
|
||
.card.success-border{border-left:3px solid var(--success)}
|
||
.card.accent-border{border-left:3px solid var(--accent)}
|
||
.card.danger-border{border-left:3px solid var(--danger)}
|
||
|
||
.section-label{text-transform:uppercase;font-size:11px;letter-spacing:.06em;color:var(--muted);margin:20px 16px 8px;font-weight:600}
|
||
|
||
.btn-primary{width:100%;background:var(--accent);color:#fff;border:none;border-radius:12px;padding:14px;font-size:15px;font-weight:600;cursor:pointer;transition:opacity .2s}
|
||
.btn-primary:hover{opacity:.9}
|
||
.btn-secondary{width:100%;background:transparent;color:var(--accent);border:1.5px solid var(--accent);border-radius:12px;padding:13px;font-size:15px;font-weight:600;cursor:pointer;transition:all .2s;margin-top:8px}
|
||
.btn-sm{padding:8px 14px;font-size:13px;font-weight:600;border-radius:9px;cursor:pointer;border:none;background:var(--accent);color:#fff}
|
||
.btn-sm.outline{background:transparent;border:1.5px solid var(--accent);color:var(--accent)}
|
||
.btn-sm.success{background:var(--success);color:#fff}
|
||
.btn-sm.danger{background:var(--danger);color:#fff}
|
||
|
||
.badge{display:inline-flex;align-items:center;padding:3px 10px;border-radius:20px;font-size:11px;font-weight:700;letter-spacing:.02em}
|
||
.badge.blue{background:#DBEAFE;color:#1D4ED8}
|
||
.badge.yellow{background:#FEF3C7;color:#D97706}
|
||
.badge.green{background:#DCFCE7;color:#15803D}
|
||
.badge.red{background:#FEE2E2;color:#DC2626}
|
||
.badge.gray{background:#F1F5F9;color:#64748B}
|
||
|
||
.form-group{margin-bottom:14px}
|
||
.form-group label{display:block;font-size:12px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-bottom:6px}
|
||
.form-input{width:100%;padding:12px 14px;border:1.5px solid #E2E8F0;border-radius:12px;font-size:15px;color:var(--ink);background:var(--card);outline:none}
|
||
.form-textarea{width:100%;padding:12px 14px;border:1.5px solid #E2E8F0;border-radius:12px;font-size:14px;color:var(--ink);background:var(--card);outline:none;resize:none;min-height:80px}
|
||
|
||
.row{display:flex;align-items:center;gap:10px}
|
||
.row.sb{justify-content:space-between}
|
||
.col{display:flex;flex-direction:column;gap:4px}
|
||
|
||
.avatar{width:40px;height:40px;border-radius:50%;background:var(--accent);display:flex;align-items:center;justify-content:center;color:#fff;font-size:15px;font-weight:700;flex-shrink:0}
|
||
.avatar.lg{width:64px;height:64px;font-size:22px}
|
||
.avatar.green{background:var(--success)}
|
||
.avatar.xl{width:80px;height:80px;font-size:28px}
|
||
|
||
.progress-bar{height:6px;background:#E2E8F0;border-radius:3px;overflow:hidden;flex:1}
|
||
.progress-fill{height:100%;background:var(--accent);border-radius:3px}
|
||
.progress-fill.green{background:var(--success)}
|
||
|
||
.divider{height:1px;background:rgba(0,0,0,.07);margin:8px 0}
|
||
|
||
.signature-canvas{width:100%;height:180px;background:#F8FAFC;border-radius:12px;border:2px dashed #CBD5E1;display:flex;align-items:center;justify-content:center;cursor:crosshair;position:relative;overflow:hidden}
|
||
.signature-canvas span{color:var(--muted);font-size:14px}
|
||
|
||
.price-item{display:flex;align-items:center;justify-content:space-between;padding:10px 0;border-bottom:1px solid #F1F5F9}
|
||
.price-item:last-child{border-bottom:none}
|
||
|
||
.info-row{display:flex;gap:8px;padding:10px 0;border-bottom:1px solid rgba(0,0,0,.06)}
|
||
.info-row:last-child{border-bottom:none}
|
||
.info-label{font-size:12px;color:var(--muted);font-weight:500;width:100px;flex-shrink:0}
|
||
.info-val{font-size:13px;font-weight:600;color:var(--ink);flex:1}
|
||
|
||
/* Timeline */
|
||
.timeline{padding:0 16px}
|
||
.tl-item{display:flex;gap:14px;padding-bottom:0}
|
||
.tl-left{display:flex;flex-direction:column;align-items:center;width:36px;flex-shrink:0}
|
||
.tl-icon{width:36px;height:36px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:16px;flex-shrink:0;border:2px solid transparent}
|
||
.tl-icon.done{background:#DCFCE7;border-color:var(--success)}
|
||
.tl-icon.active{background:var(--accent);border-color:var(--accent);box-shadow:0 0 0 4px rgba(0,62,126,.15)}
|
||
.tl-icon.pending{background:#F1F5F9;border-color:#E2E8F0}
|
||
.tl-line{width:2px;flex:1;min-height:24px;background:#E2E8F0;margin:4px 0}
|
||
.tl-line.done{background:var(--success)}
|
||
.tl-line.active{background:linear-gradient(to bottom,var(--accent),#E2E8F0)}
|
||
.tl-body{flex:1;padding-bottom:24px}
|
||
.tl-title{font-size:15px;font-weight:700;color:var(--ink);margin-bottom:3px}
|
||
.tl-title.muted{color:var(--muted)}
|
||
.tl-desc{font-size:12px;color:var(--muted);line-height:1.5}
|
||
.tl-date{font-size:11px;color:var(--muted);margin-top:4px;font-weight:600}
|
||
.tl-badge{display:inline-flex;margin-top:6px}
|
||
|
||
/* Chat bubbles */
|
||
.chat-area{padding:12px 16px;display:flex;flex-direction:column;gap:8px}
|
||
.bubble-wrap{display:flex;flex-direction:column;max-width:78%}
|
||
.bubble-wrap.me{align-self:flex-end;align-items:flex-end}
|
||
.bubble-wrap.other{align-self:flex-start;align-items:flex-start}
|
||
.bubble{padding:10px 14px;border-radius:18px;font-size:14px;line-height:1.45}
|
||
.bubble.me{background:var(--accent);color:#fff;border-bottom-right-radius:4px}
|
||
.bubble.other{background:var(--card);color:var(--ink);border-bottom-left-radius:4px;box-shadow:0 1px 4px rgba(0,0,0,.08)}
|
||
.bubble-time{font-size:10px;color:var(--muted);margin-top:2px;padding:0 4px}
|
||
.chat-sender{font-size:11px;font-weight:700;color:var(--accent);margin-bottom:3px;padding:0 4px}
|
||
.chat-input-bar{position:sticky;bottom:60px;background:var(--card);border-top:1px solid rgba(0,0,0,.07);padding:10px 12px;display:flex;align-items:center;gap:8px;z-index:20}
|
||
.chat-input{flex:1;padding:10px 14px;border:1.5px solid #E2E8F0;border-radius:22px;font-size:14px;color:var(--ink);background:var(--bg);outline:none}
|
||
.chat-send{width:38px;height:38px;border-radius:50%;background:var(--accent);border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0}
|
||
.chat-send svg{color:#fff;width:16px;height:16px}
|
||
|
||
/* Stars */
|
||
.star-row{display:flex;gap:8px;justify-content:center;margin:12px 0}
|
||
.star{font-size:36px;cursor:pointer;transition:transform .15s;filter:grayscale(1) opacity(.4)}
|
||
.star.active{filter:none;transform:scale(1.1)}
|
||
|
||
/* dark fixes */
|
||
body[data-theme="dark"] .form-input,body[data-theme="dark"] .form-textarea{background:#374151;border-color:#4B5563;color:#F9FAFB}
|
||
body[data-theme="dark"] .page-header{background:#1F2937;border-color:#374151}
|
||
body[data-theme="dark"] .bottom-nav{background:rgba(31,41,55,.95);border-color:#374151}
|
||
body[data-theme="dark"] #statusBar{background:#1F2937}
|
||
body[data-theme="dark"] .back-btn,body[data-theme="dark"] .header-action{background:#374151}
|
||
body[data-theme="dark"] .price-item{border-color:#374151}
|
||
body[data-theme="dark"] .info-row{border-color:#374151}
|
||
body[data-theme="dark"] .progress-bar{background:#374151}
|
||
body[data-theme="dark"] .tl-line{background:#374151}
|
||
body[data-theme="dark"] .tl-icon.pending{background:#374151;border-color:#4B5563}
|
||
body[data-theme="dark"] .bubble.other{background:#374151}
|
||
body[data-theme="dark"] .chat-input{background:#374151;border-color:#4B5563;color:#F9FAFB}
|
||
body[data-theme="dark"] .chat-input-bar{background:#1F2937;border-color:#374151}
|
||
body[data-theme="dark"] .signature-canvas{background:#374151;border-color:#4B5563}
|
||
|
||
@keyframes slideFade{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}
|
||
.page{animation:slideFade .18s ease-out}
|
||
</style>
|
||
</head>
|
||
<body data-theme="zov">
|
||
<div id="crm-back-nav" style="position:fixed;top:0;left:0;right:0;z-index:9999;background:rgba(255,255,255,0.92);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border-bottom:1px solid rgba(0,0,0,.08);padding:8px 16px;display:flex;align-items:center">
|
||
<a href="https://wasrusgen.github.io/wasrusgen1-crm/" style="display:inline-flex;align-items:center;gap:6px;font-family:Inter,system-ui,sans-serif;font-size:13px;font-weight:600;color:#003E7E;text-decoration:none;padding:4px 12px;border-radius:8px;background:#F0F4FF;transition:background .15s" onmouseover="this.style.background='#DDE8FF'" onmouseout="this.style.background='#F0F4FF'">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5M12 5l-7 7 7 7"/></svg>
|
||
Все кабинеты
|
||
</a>
|
||
<span style="margin-left:12px;font-family:Inter,system-ui,sans-serif;font-size:12px;color:#8A94A6">@wasrusgen1 CRM</span>
|
||
</div>
|
||
<div style="height:40px"></div>
|
||
|
||
<div id="controls">
|
||
<label>Экран:</label>
|
||
<select id="screenSelect"></select>
|
||
<div id="themeButtons">
|
||
<button class="theme-btn active" data-t="zov" onclick="setTheme('zov')">CRM</button>
|
||
<button class="theme-btn" data-t="radar" onclick="setTheme('radar')">CRM</button>
|
||
<button class="theme-btn" data-t="dark" onclick="setTheme('dark')">Dark</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="phoneWrap">
|
||
<div id="phoneFrame">
|
||
<div id="statusBar">
|
||
<span>9:41</span>
|
||
<div class="sb-right">
|
||
<svg width="16" height="12" viewBox="0 0 16 12" fill="currentColor" style="color:var(--ink)"><rect x="0" y="4" width="3" height="8" rx="1"/><rect x="4.5" y="2.5" width="3" height="9.5" rx="1"/><rect x="9" y="0.5" width="3" height="11.5" rx="1"/><rect x="13.5" y="0" width="2.5" height="12" rx="1" opacity=".3"/></svg>
|
||
<svg width="15" height="12" viewBox="0 0 15 12" fill="none" stroke="currentColor" stroke-width="1.5" style="color:var(--ink)"><path d="M7.5 3C9.5 3 11.3 3.8 12.7 5.1M2.3 5.1C3.7 3.8 5.5 3 7.5 3"/><path d="M7.5 6.5C8.7 6.5 9.8 7 10.6 7.8M4.4 7.8C5.2 7 6.3 6.5 7.5 6.5"/><circle cx="7.5" cy="10" r="1" fill="currentColor"/></svg>
|
||
<svg width="25" height="12" viewBox="0 0 25 12" fill="none" style="color:var(--ink)"><rect x="0.5" y="0.5" width="21" height="11" rx="3" stroke="currentColor" stroke-opacity=".35"/><rect x="1.5" y="1.5" width="17" height="9" rx="2" fill="currentColor"/><path d="M23 4v4a2 2 0 000-4z" fill="currentColor" fill-opacity=".4"/></svg>
|
||
</div>
|
||
</div>
|
||
<div id="screen"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
const SCREENS = {
|
||
home: 'Главная',
|
||
order_status: 'Мой заказ',
|
||
assembly_today: 'Сборка сегодня',
|
||
extra_act: 'Акт доп. работ',
|
||
extra_sign: 'Подпись акта',
|
||
extra_signed: 'Акт подписан',
|
||
chat: 'Чат с менеджером',
|
||
feedback: 'Оценка работы',
|
||
feedback_done: 'Спасибо за оценку',
|
||
profile: 'Профиль',
|
||
history: 'История заказов',
|
||
};
|
||
|
||
let cur = 'home';
|
||
const sel = document.getElementById('screenSelect');
|
||
Object.entries(SCREENS).forEach(([k,v]) => {
|
||
const o = document.createElement('option');
|
||
o.value = k; o.textContent = v; sel.appendChild(o);
|
||
});
|
||
sel.addEventListener('change', e => go(e.target.value));
|
||
|
||
function go(id) {
|
||
cur = id; sel.value = id;
|
||
const s = document.getElementById('screen');
|
||
s.innerHTML = render(id);
|
||
s.scrollTop = 0;
|
||
initCanvas();
|
||
}
|
||
|
||
function setTheme(t) {
|
||
document.body.dataset.theme = t;
|
||
document.querySelectorAll('.theme-btn').forEach(b => b.classList.toggle('active', b.dataset.t === t));
|
||
}
|
||
|
||
function nav(active) {
|
||
return `<div class="bottom-nav">
|
||
<div class="nav-item ${active==='home'?'active':''}" onclick="go('home')">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
|
||
<span>Главная</span>
|
||
</div>
|
||
<div class="nav-item ${active==='order_status'?'active':''}" onclick="go('order_status')">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="7" width="20" height="14" rx="2"/><path d="M16 7V5a2 2 0 00-2-2h-4a2 2 0 00-2 2v2"/><polyline points="12 12 12 16"/><line x1="10" y1="14" x2="14" y2="14"/></svg>
|
||
<span>Заказ</span>
|
||
</div>
|
||
<div class="nav-item ${active==='chat'?'active':''}" onclick="go('chat')">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/></svg>
|
||
<span>Чат</span>
|
||
</div>
|
||
<div class="nav-item ${active==='feedback'?'active':''}" onclick="go('feedback')">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>
|
||
<span>Оценить</span>
|
||
</div>
|
||
<div class="nav-item ${active==='profile'?'active':''}" onclick="go('profile')">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
|
||
<span>Профиль</span>
|
||
</div>
|
||
</div>`;
|
||
}
|
||
|
||
function render(id) {
|
||
switch(id) {
|
||
case 'home': return screenHome();
|
||
case 'order_status': return screenOrderStatus();
|
||
case 'assembly_today': return screenAssemblyToday();
|
||
case 'extra_act': return screenExtraAct();
|
||
case 'extra_sign': return screenExtraSign();
|
||
case 'extra_signed': return screenExtraSigned();
|
||
case 'chat': return screenChat();
|
||
case 'feedback': return screenFeedback();
|
||
case 'feedback_done': return screenFeedbackDone();
|
||
case 'profile': return screenProfile();
|
||
case 'history': return screenHistory();
|
||
default: return '<div style="padding:40px;text-align:center;color:var(--muted)">Экран в разработке</div>';
|
||
}
|
||
}
|
||
|
||
/* ─── HOME ─── */
|
||
function screenHome() {
|
||
return `<div class="page">
|
||
<div style="background:linear-gradient(135deg,var(--accent) 0%,var(--accent2) 100%);padding:24px 20px 28px">
|
||
<div style="font-size:12px;color:rgba(255,255,255,.65);font-weight:600;text-transform:uppercase;letter-spacing:.05em;margin-bottom:6px">Четверг, 21 мая 2026</div>
|
||
<div style="font-size:24px;font-weight:800;color:#fff;margin-bottom:4px">Добрый день, Дмитрий!</div>
|
||
<div style="font-size:14px;color:rgba(255,255,255,.75)">Ваша кухня уже в пути</div>
|
||
</div>
|
||
|
||
<!-- next step card -->
|
||
<div style="padding:0 16px;margin-top:-16px">
|
||
<div class="card accent-border" style="cursor:pointer" onclick="go('assembly_today')">
|
||
<div style="display:flex;align-items:center;gap:10px;margin-bottom:10px">
|
||
<div style="font-size:28px">🛠️</div>
|
||
<div>
|
||
<div style="font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)">Следующий шаг</div>
|
||
<div style="font-size:17px;font-weight:800;color:var(--ink)">Сборка — сегодня</div>
|
||
</div>
|
||
<span class="badge yellow" style="margin-left:auto">Скоро</span>
|
||
</div>
|
||
<div style="font-size:14px;color:var(--muted);margin-bottom:12px">📍 ул. Ленина, 45, кв. 12 · Сегодня в <b style="color:var(--ink)">10:00</b></div>
|
||
<div style="background:var(--bg);border-radius:10px;padding:10px 12px;display:flex;align-items:center;gap:10px">
|
||
<div class="avatar" style="width:34px;height:34px;font-size:13px;background:var(--accent2);color:#fff">АК</div>
|
||
<div>
|
||
<div style="font-size:13px;font-weight:700;color:var(--ink)">Алексей Кириллов</div>
|
||
<div style="font-size:11px;color:var(--muted)">Ваш сборщик · +7 921 456-78-90</div>
|
||
</div>
|
||
<button class="btn-sm" style="margin-left:auto;padding:6px 12px;font-size:12px" onclick="event.stopPropagation()">Позвонить</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-label">Статус заказа</div>
|
||
<div style="padding:0 16px">
|
||
<div class="card" style="cursor:pointer" onclick="go('order_status')">
|
||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px">
|
||
<div style="font-size:14px;font-weight:700;color:var(--ink)">Заказ #З-2847</div>
|
||
<span class="badge blue">Доставлено</span>
|
||
</div>
|
||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px">
|
||
<span style="font-size:12px;color:var(--muted)">Прогресс</span>
|
||
<span style="font-size:12px;font-weight:700;color:var(--ink)">Этап 3 из 4</span>
|
||
</div>
|
||
<div class="progress-bar"><div class="progress-fill" style="width:75%"></div></div>
|
||
<div style="display:flex;justify-content:space-between;margin-top:10px;font-size:11px;color:var(--muted)">
|
||
<span>Замер</span><span>Производство</span><span>Доставка</span><span style="color:var(--accent);font-weight:700">Сборка</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-label">Менеджер</div>
|
||
<div style="padding:0 16px">
|
||
<div class="card" style="display:flex;align-items:center;gap:14px">
|
||
<div class="avatar" style="background:var(--accent2);color:#fff;font-size:16px">АС</div>
|
||
<div style="flex:1">
|
||
<div style="font-size:15px;font-weight:700;color:var(--ink)">Анна Соколова</div>
|
||
<div style="font-size:12px;color:var(--muted)">Ваш менеджер · ответит за 5 мин</div>
|
||
</div>
|
||
<button class="btn-sm" onclick="go('chat')">Написать</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-label">Акт доп. работ</div>
|
||
<div style="padding:0 16px">
|
||
<div class="card warn-border" style="cursor:pointer" onclick="go('extra_act')">
|
||
<div style="display:flex;align-items:center;justify-content:space-between">
|
||
<div>
|
||
<div style="font-size:14px;font-weight:700;color:var(--ink)">Акт #DA-3f2a</div>
|
||
<div style="font-size:12px;color:var(--muted);margin-top:2px">Доставка на этаж · 3 позиции</div>
|
||
</div>
|
||
<div style="text-align:right">
|
||
<div style="font-size:18px;font-weight:800;color:var(--ink)">4 650 ₽</div>
|
||
<span class="badge yellow">Ожидает подписи</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
${nav('home')}</div>`;
|
||
}
|
||
|
||
/* ─── ORDER STATUS ─── */
|
||
function screenOrderStatus() {
|
||
const steps = [
|
||
{
|
||
key:'measure', icon:'📐', title:'Замер', done:true,
|
||
desc:'Замер выполнен 05.05.2026',
|
||
detail:'Замерщик Николай Петров · 3-комнатная кухня 3,4 м',
|
||
date:'05 мая 2026',
|
||
badge:null
|
||
},
|
||
{
|
||
key:'production', icon:'🏭', title:'Производство', done:true,
|
||
desc:'Изготовление завершено',
|
||
detail:'Кухня 3м + обеденный стол, 18 фасадов, МДФ белый матовый',
|
||
date:'15 мая 2026',
|
||
badge:null
|
||
},
|
||
{
|
||
key:'delivery', icon:'🚚', title:'Доставка', done:true,
|
||
desc:'Доставлено на адрес',
|
||
detail:'Доставка выполнена · ул. Ленина, 45, кв. 12 · всё привезено',
|
||
date:'19 мая 2026',
|
||
badge:null
|
||
},
|
||
{
|
||
key:'assembly', icon:'🛠️', title:'Сборка', done:false,
|
||
desc:'Сборщик Алексей Кириллов',
|
||
detail:'Сегодня в 10:00–14:00 · осталось дождаться сборки',
|
||
date:'21 мая 2026 · сегодня',
|
||
badge:'active'
|
||
},
|
||
];
|
||
return `<div class="page">
|
||
<div class="page-header">
|
||
<button class="back-btn" onclick="go('home')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="15 18 9 12 15 6"/></svg></button>
|
||
<h2>Мой заказ #З-2847</h2>
|
||
</div>
|
||
|
||
<div style="background:linear-gradient(135deg,var(--accent),var(--accent2));padding:16px 20px;display:flex;align-items:center;justify-content:space-between">
|
||
<div>
|
||
<div style="font-size:11px;color:rgba(255,255,255,.65);font-weight:600;text-transform:uppercase;letter-spacing:.04em">Текущий этап</div>
|
||
<div style="font-size:18px;font-weight:800;color:#fff;margin-top:2px">Сборка сегодня</div>
|
||
</div>
|
||
<div style="background:rgba(255,255,255,.18);border-radius:12px;padding:8px 14px;text-align:center">
|
||
<div style="font-size:22px;font-weight:900;color:#fff">3/4</div>
|
||
<div style="font-size:10px;color:rgba(255,255,255,.75)">этапа</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="timeline" style="margin-top:24px">
|
||
${steps.map((s, i) => `
|
||
<div class="tl-item">
|
||
<div class="tl-left">
|
||
<div class="tl-icon ${s.done ? 'done' : s.badge === 'active' ? 'active' : 'pending'}">${s.done ? '✅' : s.icon}</div>
|
||
${i < steps.length - 1 ? `<div class="tl-line ${s.done ? 'done' : s.badge === 'active' ? 'active' : ''}"></div>` : ''}
|
||
</div>
|
||
<div class="tl-body">
|
||
<div class="tl-title ${!s.done && s.badge !== 'active' ? 'muted' : ''}">${s.title}</div>
|
||
<div class="tl-desc">${s.detail}</div>
|
||
<div class="tl-date">${s.date}</div>
|
||
${s.badge === 'active' ? `<span class="badge yellow tl-badge">Сегодня</span>` : ''}
|
||
${s.done && i === 2 ? `<span class="badge green tl-badge">Выполнено</span>` : ''}
|
||
</div>
|
||
</div>
|
||
`).join('')}
|
||
</div>
|
||
|
||
<div style="padding:0 16px 0">
|
||
<div class="card" style="background:var(--bg);border:1.5px dashed #CBD5E1">
|
||
<div style="font-size:13px;font-weight:700;color:var(--muted);margin-bottom:6px">Состав заказа</div>
|
||
<div style="font-size:13px;color:var(--ink);line-height:1.7">
|
||
🪑 Кухня 3м — нижние и верхние модули<br>
|
||
🍽️ Столешница + врезная мойка<br>
|
||
🪵 Обеденный стол 1200 (раскладной)<br>
|
||
🪑 Стулья — 4 шт<br>
|
||
📦 Пенал 2100
|
||
</div>
|
||
</div>
|
||
<button class="btn-primary" onclick="go('assembly_today')">Подробнее о сборке →</button>
|
||
</div>
|
||
${nav('order_status')}</div>`;
|
||
}
|
||
|
||
/* ─── ASSEMBLY TODAY ─── */
|
||
function screenAssemblyToday() {
|
||
return `<div class="page">
|
||
<div class="page-header">
|
||
<button class="back-btn" onclick="go('home')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="15 18 9 12 15 6"/></svg></button>
|
||
<h2>Сборка сегодня</h2>
|
||
</div>
|
||
|
||
<!-- time banner -->
|
||
<div style="background:linear-gradient(135deg,var(--accent),var(--accent2));padding:18px 20px;display:flex;align-items:center;gap:14px">
|
||
<div style="font-size:36px">⏰</div>
|
||
<div>
|
||
<div style="font-size:22px;font-weight:900;color:#fff">Сегодня · 10:00–14:00</div>
|
||
<div style="font-size:13px;color:rgba(255,255,255,.75)">📍 ул. Ленина, 45, кв. 12</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- assembler card -->
|
||
<div style="padding:0 16px;margin-top:-12px">
|
||
<div class="card">
|
||
<div style="font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin-bottom:12px">Ваш сборщик</div>
|
||
<div style="display:flex;align-items:center;gap:16px;margin-bottom:16px">
|
||
<div class="avatar xl" style="background:var(--accent);font-size:26px;font-weight:800;color:#fff">АК</div>
|
||
<div>
|
||
<div style="font-size:20px;font-weight:800;color:var(--ink)">Алексей Кириллов</div>
|
||
<div style="font-size:13px;color:var(--muted);margin-top:2px">Опыт 5 лет · 340 сборок</div>
|
||
<div style="display:flex;gap:6px;margin-top:8px">
|
||
<span class="badge green">Рейтинг 4.9 ⭐</span>
|
||
<span class="badge blue">Кухни</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<a href="tel:+79214567890" style="text-decoration:none">
|
||
<button class="btn-primary" style="background:var(--success);font-size:16px;padding:16px">
|
||
📞 Позвонить · +7 921 456-78-90
|
||
</button>
|
||
</a>
|
||
<button class="btn-secondary" onclick="go('chat')" style="margin-top:8px">💬 Написать в чат</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-label">Что будет собрано</div>
|
||
<div style="padding:0 16px">
|
||
<div class="card">
|
||
${[
|
||
{icon:'🔧', name:'Кухня 3м — нижние модули', sub:'6 секций, петли, доводчики'},
|
||
{icon:'🔧', name:'Кухня 3м — верхние шкафы', sub:'5 секций'},
|
||
{icon:'🔧', name:'Столешница + мойка', sub:'Врезка, силикон'},
|
||
{icon:'🔧', name:'Пенал 2100', sub:'1 шт'},
|
||
{icon:'🔧', name:'Обеденный стол 1200', sub:'Раскладной механизм'},
|
||
{icon:'🔧', name:'Стулья — 4 шт', sub:'Ножки, болты'},
|
||
].map(i => `
|
||
<div style="display:flex;align-items:center;gap:12px;padding:10px 0;border-bottom:1px solid rgba(0,0,0,.06)">
|
||
<div style="font-size:20px;width:32px;text-align:center">${i.icon}</div>
|
||
<div>
|
||
<div style="font-size:14px;font-weight:600;color:var(--ink)">${i.name}</div>
|
||
<div style="font-size:12px;color:var(--muted)">${i.sub}</div>
|
||
</div>
|
||
</div>
|
||
`).join('')}
|
||
</div>
|
||
|
||
<div class="card" style="background:rgba(16,185,129,.07);border:1.5px solid rgba(16,185,129,.25)">
|
||
<div style="font-size:13px;color:#065F46;line-height:1.6">
|
||
✅ Убедитесь, что вы дома к <b>10:00</b><br>
|
||
✅ Освободите место на кухне<br>
|
||
✅ Сборщик свяжется за 30 мин до прибытия
|
||
</div>
|
||
</div>
|
||
</div>
|
||
${nav('order_status')}</div>`;
|
||
}
|
||
|
||
/* ─── EXTRA ACT ─── */
|
||
function screenExtraAct() {
|
||
const items = [
|
||
{name:'Доставка на этаж', qty:3, unit:'этаж', price:350},
|
||
{name:'Врезка замка', qty:2, unit:'шт', price:800},
|
||
{name:'Установка доводчиков', qty:4, unit:'шт', price:250},
|
||
];
|
||
const total = items.reduce((s,i)=>s+i.qty*i.price,0);
|
||
return `<div class="page">
|
||
<div class="page-header">
|
||
<button class="back-btn" onclick="go('home')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="15 18 9 12 15 6"/></svg></button>
|
||
<h2>Акт доп. работ</h2>
|
||
</div>
|
||
|
||
<!-- big sum banner -->
|
||
<div style="background:var(--card);padding:20px;text-align:center;border-bottom:1px solid rgba(0,0,0,.06)">
|
||
<div style="font-size:12px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.05em;margin-bottom:6px">Сумма к оплате</div>
|
||
<div style="font-size:48px;font-weight:900;color:var(--ink);line-height:1">${total.toLocaleString('ru')} ₽</div>
|
||
<div style="font-size:13px;color:var(--muted);margin-top:6px">Акт #DA-3f2a · ${items.length} позиции</div>
|
||
</div>
|
||
|
||
<div style="padding:16px">
|
||
<div class="card">
|
||
<div style="font-size:13px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-bottom:12px">Состав работ</div>
|
||
${items.map(i => `
|
||
<div class="price-item">
|
||
<div style="flex:1">
|
||
<div style="font-size:15px;font-weight:600;color:var(--ink)">${i.name}</div>
|
||
<div style="font-size:12px;color:var(--muted)">${i.qty} ${i.unit} × ${i.price} ₽</div>
|
||
</div>
|
||
<div style="font-size:16px;font-weight:800;color:var(--ink)">${(i.qty*i.price).toLocaleString('ru')} ₽</div>
|
||
</div>
|
||
`).join('')}
|
||
<div style="display:flex;justify-content:space-between;align-items:center;padding-top:14px;margin-top:4px;border-top:2px solid rgba(0,0,0,.08)">
|
||
<span style="font-size:15px;font-weight:700;color:var(--ink)">Итого</span>
|
||
<span style="font-size:22px;font-weight:900;color:var(--accent)">${total.toLocaleString('ru')} ₽</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card" style="background:var(--bg)">
|
||
<div style="font-size:12px;color:var(--muted);margin-bottom:4px;font-weight:600">Пояснение сборщика</div>
|
||
<div style="font-size:14px;color:var(--ink);line-height:1.5">Лифт не работал — доставка по лестнице. Дополнительно врезан замок на пенал. Установлены 4 доводчика на шкафы.</div>
|
||
</div>
|
||
|
||
<div style="display:flex;gap:10px;margin-top:4px">
|
||
<button class="btn-primary" style="background:var(--success)" onclick="go('extra_sign')">✅ Согласен</button>
|
||
<button class="btn-sm danger" style="flex:1;border-radius:12px;padding:14px;font-size:15px" onclick="go('chat')">Оспорить</button>
|
||
</div>
|
||
<div style="text-align:center;margin-top:10px;font-size:12px;color:var(--muted)">
|
||
Нажимая «Согласен», вы подтверждаете выполнение работ
|
||
</div>
|
||
</div>
|
||
${nav('order_status')}</div>`;
|
||
}
|
||
|
||
/* ─── EXTRA SIGN ─── */
|
||
function screenExtraSign() {
|
||
return `<div class="page">
|
||
<div class="page-header">
|
||
<button class="back-btn" onclick="go('extra_act')"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="15 18 9 12 15 6"/></svg></button>
|
||
<h2>Подпись акта</h2>
|
||
</div>
|
||
<div style="padding:16px">
|
||
<div class="card" style="text-align:center;margin-bottom:16px">
|
||
<div style="font-size:32px;margin-bottom:8px">📋</div>
|
||
<div style="font-size:18px;font-weight:800;color:var(--ink);margin-bottom:4px">Акт доп. работ #DA-3f2a</div>
|
||
<div style="font-size:28px;font-weight:900;color:var(--accent);margin:8px 0">4 650 ₽</div>
|
||
<div style="font-size:13px;color:var(--muted);line-height:1.5">
|
||
Доставка на этаж, врезка замка,<br>установка доводчиков
|
||
</div>
|
||
<div style="margin-top:12px;padding-top:12px;border-top:1px solid rgba(0,0,0,.06)">
|
||
<div class="info-row" style="padding:6px 0"><span class="info-label">Клиент</span><span class="info-val">Иванов Дмитрий</span></div>
|
||
<div class="info-row" style="padding:6px 0"><span class="info-label">Дата</span><span class="info-val">21.05.2026</span></div>
|
||
<div class="info-row" style="padding:6px 0"><span class="info-label">Сборщик</span><span class="info-val">Алексей Кириллов</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="font-size:14px;font-weight:700;color:var(--ink);margin-bottom:8px">Ваша подпись</div>
|
||
<canvas id="sigCanvas" width="358" height="160" style="width:100%;height:160px;background:#F8FAFC;border-radius:12px;border:2px dashed #CBD5E1;cursor:crosshair;touch-action:none;display:block"></canvas>
|
||
<div style="display:flex;justify-content:space-between;margin-top:8px">
|
||
<span style="font-size:12px;color:var(--muted)">Нарисуйте подпись пальцем</span>
|
||
<button class="btn-sm outline" style="font-size:12px;padding:5px 12px" onclick="clearSig()">Очистить</button>
|
||
</div>
|
||
|
||
<div style="margin-top:14px;padding:12px;background:rgba(0,0,0,.03);border-radius:12px;font-size:12px;color:var(--muted);line-height:1.5">
|
||
Подписывая акт, вы подтверждаете выполнение дополнительных работ и согласие с указанной стоимостью.
|
||
</div>
|
||
|
||
<div style="margin-top:16px">
|
||
<button class="btn-primary" onclick="go('extra_signed')">✅ Подписать и отправить</button>
|
||
</div>
|
||
</div>
|
||
${nav('order_status')}</div>`;
|
||
}
|
||
|
||
/* ─── EXTRA SIGNED ─── */
|
||
function screenExtraSigned() {
|
||
return `<div class="page">
|
||
<div style="padding:80px 24px 24px;text-align:center">
|
||
<div style="width:96px;height:96px;background:#DCFCE7;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:48px;margin:0 auto 24px">✅</div>
|
||
<div style="font-size:28px;font-weight:900;color:var(--ink);margin-bottom:10px">Акт подписан!</div>
|
||
<div style="font-size:15px;color:var(--muted);line-height:1.6;margin-bottom:32px">
|
||
Акт #DA-3f2a на сумму <b style="color:var(--ink)">4 650 ₽</b><br>успешно подписан и отправлен менеджеру
|
||
</div>
|
||
|
||
<div class="card" style="text-align:left;margin-bottom:28px">
|
||
<div class="info-row"><span class="info-label">Акт</span><span class="info-val">#DA-3f2a</span></div>
|
||
<div class="info-row"><span class="info-label">Клиент</span><span class="info-val">Иванов Дмитрий</span></div>
|
||
<div class="info-row"><span class="info-label">Сумма</span><span class="info-val" style="color:var(--success);font-weight:800">4 650 ₽</span></div>
|
||
<div class="info-row"><span class="info-label">Подписан</span><span class="info-val">21.05.2026, 11:42</span></div>
|
||
<div class="info-row"><span class="info-label">Статус</span><span class="info-val"><span class="badge green">Подписан</span></span></div>
|
||
</div>
|
||
|
||
<button class="btn-primary" onclick="go('feedback')">Оценить работу сборщика →</button>
|
||
<button class="btn-secondary" onclick="go('home')">На главную</button>
|
||
</div>
|
||
${nav('order_status')}</div>`;
|
||
}
|
||
|
||
/* ─── CHAT ─── */
|
||
function screenChat() {
|
||
const msgs = [
|
||
{me:false, name:'Анна Соколова', text:'Дмитрий, добрый день! Ваша кухня уже доставлена. Сборщик Алексей подъедет к 10:00. Всё в порядке?', time:'9:05'},
|
||
{me:true, text:'Добрый день! Да, всё хорошо. Жду. А лифт у нас не работает, он в курсе?', time:'9:12'},
|
||
{me:false, name:'Анна Соколова', text:'Предупредила Алексея. Он оформит акт на доставку по лестнице — нужно будет подписать. Ориентировочная сумма 1 050 ₽.', time:'9:14'},
|
||
{me:true, text:'Понял, спасибо за предупреждение!', time:'9:15'},
|
||
];
|
||
return `<div class="page">
|
||
<div class="page-header">
|
||
<h2>Чат с менеджером</h2>
|
||
<div style="display:flex;align-items:center;gap:8px">
|
||
<div class="avatar" style="width:30px;height:30px;font-size:12px;background:var(--accent2)">АС</div>
|
||
<div>
|
||
<div style="font-size:12px;font-weight:700;color:var(--ink)">Анна Соколова</div>
|
||
<div style="font-size:10px;color:var(--success)">● онлайн</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="background:var(--bg);padding:8px 16px;font-size:11px;color:var(--muted);text-align:center;border-bottom:1px solid rgba(0,0,0,.05)">
|
||
Сегодня, 21 мая
|
||
</div>
|
||
|
||
<div class="chat-area">
|
||
${msgs.map(m => `
|
||
<div class="bubble-wrap ${m.me?'me':'other'}">
|
||
${!m.me ? `<div class="chat-sender">${m.name}</div>` : ''}
|
||
<div class="bubble ${m.me?'me':'other'}">${m.text}</div>
|
||
<div class="bubble-time">${m.time}</div>
|
||
</div>
|
||
`).join('')}
|
||
</div>
|
||
|
||
<div class="chat-input-bar">
|
||
<input class="chat-input" placeholder="Написать сообщение...">
|
||
<button class="chat-send">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
|
||
</button>
|
||
</div>
|
||
${nav('chat')}</div>`;
|
||
}
|
||
|
||
/* ─── FEEDBACK ─── */
|
||
function screenFeedback() {
|
||
return `<div class="page">
|
||
<div class="page-header">
|
||
<h2>Оценить работу</h2>
|
||
</div>
|
||
<div style="padding:24px 16px">
|
||
|
||
<!-- assembler -->
|
||
<div style="text-align:center;margin-bottom:24px">
|
||
<div class="avatar xl" style="margin:0 auto 12px;background:var(--accent);font-size:28px;font-weight:800">АК</div>
|
||
<div style="font-size:20px;font-weight:800;color:var(--ink)">Алексей Кириллов</div>
|
||
<div style="font-size:13px;color:var(--muted);margin-top:4px">Сборщик · Сборка #З-2847</div>
|
||
</div>
|
||
|
||
<div class="card" style="text-align:center">
|
||
<div style="font-size:15px;font-weight:700;color:var(--ink);margin-bottom:4px">Как оцените работу?</div>
|
||
<div style="font-size:13px;color:var(--muted);margin-bottom:12px">Нажмите на звезду</div>
|
||
<div class="star-row" id="starRow">
|
||
<span class="star active" data-v="1" onclick="rateStar(1)">⭐</span>
|
||
<span class="star active" data-v="2" onclick="rateStar(2)">⭐</span>
|
||
<span class="star active" data-v="3" onclick="rateStar(3)">⭐</span>
|
||
<span class="star active" data-v="4" onclick="rateStar(4)">⭐</span>
|
||
<span class="star" data-v="5" onclick="rateStar(5)">⭐</span>
|
||
</div>
|
||
<div id="rateLabel" style="font-size:14px;font-weight:700;color:var(--accent);margin-bottom:4px">Хорошо</div>
|
||
</div>
|
||
|
||
<div class="form-group" style="margin-top:4px">
|
||
<label>Ваш отзыв</label>
|
||
<textarea class="form-textarea" rows="4" placeholder="Расскажите о работе сборщика...">Всё собрано аккуратно и быстро. Алексей предупредил про нюансы с петлями на пенале, объяснил как регулировать фасады. Очень доволен!</textarea>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Качество сборки</label>
|
||
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
||
${['Аккуратно','Быстро','Без мусора','Вежливый','Объяснил нюансы'].map((t,i) => `
|
||
<div style="padding:7px 14px;border-radius:20px;font-size:13px;font-weight:600;cursor:pointer;border:1.5px solid ${i<3?'var(--accent)':'#E2E8F0'};background:${i<3?'var(--accent)':'transparent'};color:${i<3?'#fff':'var(--muted)'}">${t}</div>
|
||
`).join('')}
|
||
</div>
|
||
</div>
|
||
|
||
<button class="btn-primary" style="background:var(--success)" onclick="go('feedback_done')">Отправить оценку</button>
|
||
</div>
|
||
${nav('feedback')}</div>`;
|
||
}
|
||
|
||
/* ─── FEEDBACK DONE ─── */
|
||
function screenFeedbackDone() {
|
||
return `<div class="page">
|
||
<div style="padding:80px 24px 24px;text-align:center">
|
||
<div style="width:96px;height:96px;background:#FEF3C7;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:48px;margin:0 auto 24px">⭐</div>
|
||
<div style="font-size:28px;font-weight:900;color:var(--ink);margin-bottom:10px">Спасибо за оценку!</div>
|
||
<div style="font-size:15px;color:var(--muted);line-height:1.6;margin-bottom:32px">
|
||
Ваш отзыв об Алексее Кириллове<br>уже отправлен. Рады, что вам понравилось!
|
||
</div>
|
||
|
||
<div class="card" style="display:flex;align-items:center;gap:16px;text-align:left;margin-bottom:28px">
|
||
<div class="avatar" style="background:var(--accent);font-size:18px;font-weight:800">АК</div>
|
||
<div>
|
||
<div style="font-size:15px;font-weight:700;color:var(--ink)">Алексей Кириллов</div>
|
||
<div style="font-size:24px;margin-top:2px">⭐⭐⭐⭐</div>
|
||
<div style="font-size:12px;color:var(--muted);margin-top:2px">Ваша оценка принята</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="background:rgba(16,185,129,.08);border-radius:16px;padding:16px;margin-bottom:24px">
|
||
<div style="font-size:14px;color:#065F46;font-weight:600;margin-bottom:4px">Ваш заказ выполнен!</div>
|
||
<div style="font-size:13px;color:#047857;line-height:1.5">Кухня собрана. Если понадобится гарантийный сервис — пишите нам.</div>
|
||
</div>
|
||
|
||
<button class="btn-primary" onclick="go('home')">На главную</button>
|
||
</div>
|
||
${nav('feedback')}</div>`;
|
||
}
|
||
|
||
/* ─── PROFILE ─── */
|
||
function screenProfile() {
|
||
return `<div class="page">
|
||
<div class="page-header">
|
||
<h2>Профиль</h2>
|
||
</div>
|
||
<div style="padding:20px 16px 0">
|
||
|
||
<!-- hero -->
|
||
<div style="display:flex;align-items:center;gap:16px;margin-bottom:20px">
|
||
<div class="avatar xl" style="background:var(--accent);font-size:26px;font-weight:800">ИД</div>
|
||
<div>
|
||
<div style="font-size:22px;font-weight:900;color:var(--ink)">Иванов Дмитрий</div>
|
||
<div style="font-size:14px;color:var(--muted);margin-top:2px">+7 921 234-56-78</div>
|
||
<div style="margin-top:8px"><span class="badge green">Клиент</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- contacts -->
|
||
<div class="card">
|
||
<div style="font-size:13px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-bottom:12px">Контактные данные</div>
|
||
<div class="info-row"><span class="info-label">Имя</span><span class="info-val">Иванов Дмитрий Александрович</span></div>
|
||
<div class="info-row"><span class="info-label">Телефон</span><span class="info-val" style="color:var(--accent)">+7 921 234-56-78</span></div>
|
||
<div class="info-row"><span class="info-label">Email</span><span class="info-val">ivanov.d@mail.ru</span></div>
|
||
</div>
|
||
|
||
<!-- addresses -->
|
||
<div class="card">
|
||
<div style="font-size:13px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-bottom:12px">Адреса</div>
|
||
<div class="info-row">
|
||
<span class="info-label">Основной</span>
|
||
<div style="flex:1">
|
||
<div class="info-val">ул. Ленина, 45, кв. 12</div>
|
||
<div style="font-size:11px;color:var(--muted);margin-top:2px">Санкт-Петербург, 190031</div>
|
||
</div>
|
||
</div>
|
||
<div class="info-row">
|
||
<span class="info-label">Дача</span>
|
||
<div style="flex:1">
|
||
<div class="info-val">пос. Заречный, ул. Садовая 7</div>
|
||
<div style="font-size:11px;color:var(--muted);margin-top:2px">Лен. область</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- order history -->
|
||
<div style="display:flex;align-items:center;justify-content:space-between;margin:16px 0 8px">
|
||
<div style="font-size:11px;font-weight:700;letter-spacing:.06em;color:var(--muted);text-transform:uppercase">Мои заказы</div>
|
||
<button onclick="go('history')" style="background:none;border:none;font-size:13px;font-weight:700;color:var(--accent);cursor:pointer">Все →</button>
|
||
</div>
|
||
${[
|
||
{id:'З-2847', name:'Кухня 3м + стол', date:'21.05.2026', badge:'yellow', label:'В процессе'},
|
||
{id:'З-2104', name:'Шкаф-купе 3-дв.', date:'14.02.2026', badge:'green', label:'Завершён'},
|
||
{id:'З-1831', name:'Детская мебель', date:'08.11.2025', badge:'green', label:'Завершён'},
|
||
].map(o => `
|
||
<div class="card" style="cursor:pointer">
|
||
<div style="display:flex;align-items:center;justify-content:space-between">
|
||
<div>
|
||
<div style="font-size:14px;font-weight:700;color:var(--ink)">${o.name}</div>
|
||
<div style="font-size:12px;color:var(--muted);margin-top:2px">Заказ #${o.id} · ${o.date}</div>
|
||
</div>
|
||
<span class="badge ${o.badge}">${o.label}</span>
|
||
</div>
|
||
</div>
|
||
`).join('')}
|
||
|
||
<button class="btn-secondary" style="margin-bottom:8px">🚪 Выйти</button>
|
||
</div>
|
||
${nav('profile')}</div>`;
|
||
}
|
||
|
||
/* ─── HISTORY ─── */
|
||
function screenHistory() {
|
||
const bk = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M15 18l-6-6 6-6"/></svg>';
|
||
const orders = [
|
||
{id:'З-2847', icon:'🍳', name:'Кухня 3м + обеденный стол', date:'21.05.2026', badge:'yellow', label:'В процессе', price:'128 500 ₽', step:'3 из 4'},
|
||
{id:'З-2104', icon:'🚪', name:'Шкаф-купе трёхдверный', date:'14.02.2026', badge:'green', label:'Завершён', price:'47 800 ₽', step:'4 из 4'},
|
||
{id:'З-1831', icon:'🧸', name:'Детская мебель — полный комплект', date:'08.11.2025', badge:'green', label:'Завершён', price:'89 200 ₽', step:'4 из 4'},
|
||
{id:'З-1245', icon:'🛏️', name:'Спальня: кровать + 2 тумбы', date:'03.06.2025', badge:'green', label:'Завершён', price:'62 400 ₽', step:'4 из 4'},
|
||
];
|
||
return `<div class="page">
|
||
<div class="page-header">
|
||
<button class="back-btn" onclick="go('profile')">${bk}</button>
|
||
<h2>История заказов</h2>
|
||
</div>
|
||
|
||
<div style="padding:12px 16px 4px">
|
||
<div style="background:var(--card);border-radius:14px;padding:14px 16px;display:flex;box-shadow:0 2px 12px rgba(0,0,0,.07)">
|
||
<div style="flex:1;text-align:center;border-right:1px solid rgba(0,0,0,.07)">
|
||
<div style="font-size:22px;font-weight:800;color:var(--ink)">4</div>
|
||
<div style="font-size:11px;color:var(--muted);margin-top:2px">Заказа</div>
|
||
</div>
|
||
<div style="flex:1;text-align:center;border-right:1px solid rgba(0,0,0,.07)">
|
||
<div style="font-size:22px;font-weight:800;color:var(--success)">3</div>
|
||
<div style="font-size:11px;color:var(--muted);margin-top:2px">Завершено</div>
|
||
</div>
|
||
<div style="flex:1;text-align:center">
|
||
<div style="font-size:20px;font-weight:800;color:var(--warn)">328 ₽тыс</div>
|
||
<div style="font-size:11px;color:var(--muted);margin-top:2px">Всего</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-label">Все заказы</div>
|
||
<div style="padding:0 16px">
|
||
${orders.map(o => `
|
||
<div class="card ${o.badge==='yellow'?'accent-border':'success-border'}" onclick="go('order_status')" style="cursor:pointer">
|
||
<div style="display:flex;align-items:flex-start;gap:12px">
|
||
<div style="font-size:30px;line-height:1.1">${o.icon}</div>
|
||
<div style="flex:1">
|
||
<div style="display:flex;align-items:flex-start;justify-content:space-between;gap:6px;margin-bottom:5px">
|
||
<div style="font-size:14px;font-weight:700;color:var(--ink);flex:1">${o.name}</div>
|
||
<span class="badge ${o.badge}">${o.label}</span>
|
||
</div>
|
||
<div style="font-size:12px;color:var(--muted)">Заказ #${o.id} · ${o.date}</div>
|
||
<div style="display:flex;align-items:center;justify-content:space-between;margin-top:6px">
|
||
<span style="font-size:14px;font-weight:800;color:var(--accent)">${o.price}</span>
|
||
<span style="font-size:11px;color:var(--muted)">Этап ${o.step}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`).join('')}
|
||
</div>
|
||
${nav('profile')}</div>`;
|
||
}
|
||
|
||
/* ─── Canvas signature ─── */
|
||
function initCanvas() {
|
||
const c = document.getElementById('sigCanvas');
|
||
if (!c) return;
|
||
const ctx = c.getContext('2d');
|
||
let drawing = false;
|
||
ctx.strokeStyle = '#003E7E';
|
||
ctx.lineWidth = 2.5;
|
||
ctx.lineCap = 'round';
|
||
|
||
function pos(e) {
|
||
const r = c.getBoundingClientRect();
|
||
const src = e.touches ? e.touches[0] : e;
|
||
return [(src.clientX - r.left) * (c.width / r.width), (src.clientY - r.top) * (c.height / r.height)];
|
||
}
|
||
c.addEventListener('mousedown', e => { drawing=true; ctx.beginPath(); ctx.moveTo(...pos(e)); });
|
||
c.addEventListener('mousemove', e => { if(!drawing) return; ctx.lineTo(...pos(e)); ctx.stroke(); });
|
||
c.addEventListener('mouseup', () => drawing=false);
|
||
c.addEventListener('touchstart', e => { e.preventDefault(); drawing=true; ctx.beginPath(); ctx.moveTo(...pos(e)); });
|
||
c.addEventListener('touchmove', e => { e.preventDefault(); if(!drawing) return; ctx.lineTo(...pos(e)); ctx.stroke(); });
|
||
c.addEventListener('touchend', () => drawing=false);
|
||
}
|
||
|
||
function clearSig() {
|
||
const c = document.getElementById('sigCanvas');
|
||
if (c) c.getContext('2d').clearRect(0,0,c.width,c.height);
|
||
}
|
||
|
||
function rateStar(n) {
|
||
document.querySelectorAll('.star').forEach((s,i) => s.classList.toggle('active', i < n));
|
||
const labels = ['','Плохо','Неплохо','Нормально','Хорошо','Отлично!'];
|
||
const el = document.getElementById('rateLabel');
|
||
if (el) el.textContent = labels[n];
|
||
}
|
||
|
||
// init
|
||
go('home');
|
||
</script>
|
||
</body>
|
||
</html>
|
||
|