feat: add character illustrations to dashboard
Adds four hand-drawn flat-style SVG mascots: - recruiter.svg — woman at a laptop, paired with the workload block - candidate.svg — smiling candidate with a resume, paired with the manual-overrides block - thinker.svg — person thinking with a lightbulb thought bubble, paired with the simulator block - team.svg — three teammates in a row, paired with the functions table Adds a .block.with-mascot grid layout so each illustration sits beside its block and collapses above the body on narrow screens. Hover scales the figure slightly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ea42399925
commit
1244c52e41
39
assets/candidate.svg
Normal file
39
assets/candidate.svg
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 220" width="100%" height="100%">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="cbg" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0%" stop-color="#34d399" stop-opacity=".22"/>
|
||||||
|
<stop offset="100%" stop-color="#60a5fa" stop-opacity=".05"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<circle cx="110" cy="110" r="100" fill="url(#cbg)"/>
|
||||||
|
|
||||||
|
<!-- resume sheet -->
|
||||||
|
<g transform="translate(140 100) rotate(10)">
|
||||||
|
<rect x="0" y="0" width="60" height="80" rx="4" fill="white" stroke="#cbd5e1" stroke-width="1.5"/>
|
||||||
|
<rect x="0" y="0" width="60" height="14" fill="#60a5fa" rx="4"/>
|
||||||
|
<circle cx="12" cy="22" r="4" fill="#60a5fa"/>
|
||||||
|
<line x1="20" y1="22" x2="50" y2="22" stroke="#cbd5e1" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<line x1="8" y1="34" x2="52" y2="34" stroke="#cbd5e1" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<line x1="8" y1="42" x2="46" y2="42" stroke="#cbd5e1" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<line x1="8" y1="50" x2="52" y2="50" stroke="#cbd5e1" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<line x1="8" y1="58" x2="40" y2="58" stroke="#cbd5e1" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<line x1="8" y1="66" x2="50" y2="66" stroke="#cbd5e1" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- body -->
|
||||||
|
<path d="M55 200 Q55 130 95 130 Q135 130 135 200 Z" fill="#34d399"/>
|
||||||
|
<!-- tie -->
|
||||||
|
<polygon points="92,138 98,138 98,165 95,180 92,165" fill="#1e3a8a"/>
|
||||||
|
|
||||||
|
<!-- head -->
|
||||||
|
<circle cx="95" cy="90" r="30" fill="#fde68a"/>
|
||||||
|
<!-- hair -->
|
||||||
|
<path d="M65 88 Q65 56 95 56 Q125 56 125 88 Q120 68 95 68 Q70 68 65 88" fill="#451a03"/>
|
||||||
|
<!-- eyes -->
|
||||||
|
<circle cx="85" cy="92" r="2.5" fill="#1e293b"/>
|
||||||
|
<circle cx="105" cy="92" r="2.5" fill="#1e293b"/>
|
||||||
|
<!-- big smile -->
|
||||||
|
<path d="M82 104 Q95 116 108 104" stroke="#92400e" stroke-width="2.2" fill="none" stroke-linecap="round"/>
|
||||||
|
<!-- arm holding resume -->
|
||||||
|
<path d="M125 145 L150 130" stroke="#34d399" stroke-width="14" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
38
assets/recruiter.svg
Normal file
38
assets/recruiter.svg
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240" width="100%" height="100%">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="rbg" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0%" stop-color="#a78bfa" stop-opacity=".25"/>
|
||||||
|
<stop offset="100%" stop-color="#60a5fa" stop-opacity=".05"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<circle cx="120" cy="120" r="110" fill="url(#rbg)"/>
|
||||||
|
<!-- desk -->
|
||||||
|
<rect x="40" y="170" width="160" height="14" rx="2" fill="#94a3b8"/>
|
||||||
|
<rect x="50" y="184" width="6" height="38" fill="#64748b"/>
|
||||||
|
<rect x="184" y="184" width="6" height="38" fill="#64748b"/>
|
||||||
|
<!-- laptop -->
|
||||||
|
<rect x="80" y="140" width="80" height="50" rx="4" fill="#1e293b"/>
|
||||||
|
<rect x="86" y="146" width="68" height="38" rx="2" fill="#60a5fa"/>
|
||||||
|
<rect x="92" y="152" width="30" height="3" fill="white" opacity=".8"/>
|
||||||
|
<rect x="92" y="160" width="40" height="3" fill="white" opacity=".5"/>
|
||||||
|
<rect x="92" y="168" width="22" height="3" fill="white" opacity=".5"/>
|
||||||
|
<rect x="70" y="186" width="100" height="6" rx="2" fill="#334155"/>
|
||||||
|
<!-- person body -->
|
||||||
|
<path d="M85 150 Q85 110 120 110 Q155 110 155 150" fill="#8b5cf6"/>
|
||||||
|
<!-- head -->
|
||||||
|
<circle cx="120" cy="80" r="28" fill="#fde68a"/>
|
||||||
|
<!-- hair -->
|
||||||
|
<path d="M92 78 Q92 50 120 50 Q148 50 148 78 Q145 60 120 60 Q95 60 92 78" fill="#451a03"/>
|
||||||
|
<path d="M92 80 Q90 100 100 105 L100 85 Z" fill="#451a03"/>
|
||||||
|
<!-- eyes -->
|
||||||
|
<circle cx="110" cy="80" r="2.5" fill="#1e293b"/>
|
||||||
|
<circle cx="130" cy="80" r="2.5" fill="#1e293b"/>
|
||||||
|
<!-- smile -->
|
||||||
|
<path d="M112 92 Q120 98 128 92" stroke="#92400e" stroke-width="2" fill="none" stroke-linecap="round"/>
|
||||||
|
<!-- arm typing -->
|
||||||
|
<path d="M95 130 L80 155" stroke="#8b5cf6" stroke-width="12" stroke-linecap="round"/>
|
||||||
|
<path d="M145 130 L160 155" stroke="#8b5cf6" stroke-width="12" stroke-linecap="round"/>
|
||||||
|
<!-- speech bubble -->
|
||||||
|
<circle cx="190" cy="40" r="22" fill="white" stroke="#60a5fa" stroke-width="2"/>
|
||||||
|
<text x="190" y="46" text-anchor="middle" font-family="-apple-system, sans-serif" font-size="18" fill="#60a5fa">💼</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
47
assets/team.svg
Normal file
47
assets/team.svg
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 200" width="100%" height="100%">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="tbg" x1="0" y1="0" x2="1" y2="1">
|
||||||
|
<stop offset="0%" stop-color="#34d399" stop-opacity=".15"/>
|
||||||
|
<stop offset="100%" stop-color="#60a5fa" stop-opacity=".05"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<rect width="300" height="200" rx="20" fill="url(#tbg)"/>
|
||||||
|
|
||||||
|
<!-- person 1 -->
|
||||||
|
<g transform="translate(40 50)">
|
||||||
|
<circle cx="30" cy="30" r="22" fill="#fbbf24"/>
|
||||||
|
<path d="M14 28 Q14 8 30 8 Q46 8 46 28" fill="#1e293b"/>
|
||||||
|
<circle cx="24" cy="32" r="2" fill="#1e293b"/>
|
||||||
|
<circle cx="36" cy="32" r="2" fill="#1e293b"/>
|
||||||
|
<path d="M25 42 Q30 46 35 42" stroke="#92400e" stroke-width="1.5" fill="none" stroke-linecap="round"/>
|
||||||
|
<path d="M0 110 Q0 70 30 70 Q60 70 60 110 Z" fill="#60a5fa"/>
|
||||||
|
<rect x="5" y="105" width="50" height="35" fill="#60a5fa"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- person 2 (taller) -->
|
||||||
|
<g transform="translate(110 30)">
|
||||||
|
<circle cx="30" cy="30" r="24" fill="#fde68a"/>
|
||||||
|
<path d="M12 28 Q12 4 30 4 Q48 4 48 28 Q46 14 30 14 Q14 14 12 28" fill="#451a03"/>
|
||||||
|
<circle cx="23" cy="32" r="2" fill="#1e293b"/>
|
||||||
|
<circle cx="37" cy="32" r="2" fill="#1e293b"/>
|
||||||
|
<path d="M24 44 Q30 48 36 44" stroke="#92400e" stroke-width="1.5" fill="none" stroke-linecap="round"/>
|
||||||
|
<path d="M-4 130 Q-4 80 30 80 Q64 80 64 130 Z" fill="#a78bfa"/>
|
||||||
|
<rect x="0" y="125" width="60" height="35" fill="#a78bfa"/>
|
||||||
|
<!-- folder -->
|
||||||
|
<rect x="48" y="92" width="22" height="28" rx="2" fill="#fbbf24" transform="rotate(8 60 106)"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- person 3 -->
|
||||||
|
<g transform="translate(195 50)">
|
||||||
|
<circle cx="30" cy="30" r="22" fill="#fda4af"/>
|
||||||
|
<path d="M12 30 Q12 6 30 6 Q48 6 48 30 Q40 10 30 10 Q20 10 12 30" fill="#7c2d12"/>
|
||||||
|
<circle cx="24" cy="32" r="2" fill="#1e293b"/>
|
||||||
|
<circle cx="36" cy="32" r="2" fill="#1e293b"/>
|
||||||
|
<path d="M25 42 Q30 46 35 42" stroke="#92400e" stroke-width="1.5" fill="none" stroke-linecap="round"/>
|
||||||
|
<path d="M0 110 Q0 70 30 70 Q60 70 60 110 Z" fill="#34d399"/>
|
||||||
|
<rect x="5" y="105" width="50" height="35" fill="#34d399"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- floor shadow -->
|
||||||
|
<ellipse cx="150" cy="186" rx="120" ry="6" fill="black" opacity=".08"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.2 KiB |
41
assets/thinker.svg
Normal file
41
assets/thinker.svg
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 220" width="100%" height="100%">
|
||||||
|
<defs>
|
||||||
|
<radialGradient id="thbg" cx="50%" cy="50%" r="60%">
|
||||||
|
<stop offset="0%" stop-color="#fbbf24" stop-opacity=".2"/>
|
||||||
|
<stop offset="100%" stop-color="#f87171" stop-opacity="0"/>
|
||||||
|
</radialGradient>
|
||||||
|
</defs>
|
||||||
|
<rect width="220" height="220" fill="url(#thbg)"/>
|
||||||
|
|
||||||
|
<!-- thought bubbles -->
|
||||||
|
<circle cx="155" cy="35" r="6" fill="white" stroke="#94a3b8" stroke-width="1.5"/>
|
||||||
|
<circle cx="170" cy="55" r="9" fill="white" stroke="#94a3b8" stroke-width="1.5"/>
|
||||||
|
<circle cx="195" cy="80" r="22" fill="white" stroke="#94a3b8" stroke-width="2"/>
|
||||||
|
<text x="195" y="88" text-anchor="middle" font-family="-apple-system, sans-serif" font-size="20">💡</text>
|
||||||
|
|
||||||
|
<!-- chair -->
|
||||||
|
<rect x="50" y="170" width="100" height="14" rx="2" fill="#64748b"/>
|
||||||
|
<rect x="55" y="184" width="6" height="30" fill="#64748b"/>
|
||||||
|
<rect x="139" y="184" width="6" height="30" fill="#64748b"/>
|
||||||
|
|
||||||
|
<!-- body -->
|
||||||
|
<path d="M65 170 Q65 110 105 110 Q145 110 145 170 Z" fill="#3b82f6"/>
|
||||||
|
<!-- legs -->
|
||||||
|
<rect x="78" y="160" width="14" height="40" rx="4" fill="#1e293b"/>
|
||||||
|
<rect x="118" y="160" width="14" height="40" rx="4" fill="#1e293b"/>
|
||||||
|
|
||||||
|
<!-- head -->
|
||||||
|
<circle cx="105" cy="85" r="28" fill="#fde68a"/>
|
||||||
|
<!-- hair -->
|
||||||
|
<path d="M77 85 Q77 55 105 55 Q133 55 133 85 Q128 65 105 65 Q82 65 77 85" fill="#1e293b"/>
|
||||||
|
<!-- eyes -->
|
||||||
|
<circle cx="95" cy="86" r="2.5" fill="#1e293b"/>
|
||||||
|
<circle cx="115" cy="86" r="2.5" fill="#1e293b"/>
|
||||||
|
<!-- thinking mouth -->
|
||||||
|
<path d="M97 100 L113 100" stroke="#92400e" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<!-- chin hand -->
|
||||||
|
<path d="M115 105 L130 95" stroke="#fde68a" stroke-width="10" stroke-linecap="round"/>
|
||||||
|
<circle cx="130" cy="95" r="7" fill="#fde68a"/>
|
||||||
|
<!-- arm -->
|
||||||
|
<path d="M132 110 L150 90" stroke="#3b82f6" stroke-width="14" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
26
index.html
26
index.html
@ -51,12 +51,17 @@
|
|||||||
<div id="strategic-kpi" class="kpi-grid"></div>
|
<div id="strategic-kpi" class="kpi-grid"></div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="block">
|
<section class="block with-mascot">
|
||||||
<h2>👤 Нагрузка на сотрудника (дни и недели)</h2>
|
<img src="./assets/recruiter.svg" alt="" class="mascot" loading="lazy">
|
||||||
<div id="workload-kpi" class="kpi-grid"></div>
|
<div class="block-body">
|
||||||
|
<h2>👤 Нагрузка на сотрудника (дни и недели)</h2>
|
||||||
|
<div id="workload-kpi" class="kpi-grid"></div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="block">
|
<section class="block with-mascot mascot-right">
|
||||||
|
<img src="./assets/candidate.svg" alt="" class="mascot" loading="lazy">
|
||||||
|
<div class="block-body">
|
||||||
<h2>✏️ Ручные правки времени (без изменения xlsx)</h2>
|
<h2>✏️ Ручные правки времени (без изменения xlsx)</h2>
|
||||||
<p class="hint">Заменить минуты конкретной функции по №. Влияет на все KPI и графики. Пусто = убрать правку.</p>
|
<p class="hint">Заменить минуты конкретной функции по №. Влияет на все KPI и графики. Пусто = убрать правку.</p>
|
||||||
<div class="ovr-form">
|
<div class="ovr-form">
|
||||||
@ -66,9 +71,12 @@
|
|||||||
<button type="button" id="ovr-clear" class="secondary">Очистить все</button>
|
<button type="button" id="ovr-clear" class="secondary">Очистить все</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="ovr-list" class="ovr-list"></div>
|
<div id="ovr-list" class="ovr-list"></div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="block">
|
<section class="block with-mascot">
|
||||||
|
<img src="./assets/thinker.svg" alt="" class="mascot" loading="lazy">
|
||||||
|
<div class="block-body">
|
||||||
<h2>🧪 Симулятор «что если»</h2>
|
<h2>🧪 Симулятор «что если»</h2>
|
||||||
<p class="hint">Не меняет исходные данные. Покажет, как изменятся KPI при заданных условиях.</p>
|
<p class="hint">Не меняет исходные данные. Покажет, как изменятся KPI при заданных условиях.</p>
|
||||||
<label class="sim-toggle"><input type="checkbox" id="sim-toggle"> Включить симулятор</label>
|
<label class="sim-toggle"><input type="checkbox" id="sim-toggle"> Включить симулятор</label>
|
||||||
@ -101,6 +109,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="sim-output" hidden></div>
|
<div id="sim-output" hidden></div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="block">
|
<section class="block">
|
||||||
@ -142,7 +151,9 @@
|
|||||||
<div id="chart-treemap"></div>
|
<div id="chart-treemap"></div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="block">
|
<section class="block with-mascot mascot-right mascot-wide">
|
||||||
|
<img src="./assets/team.svg" alt="" class="mascot" loading="lazy">
|
||||||
|
<div class="block-body">
|
||||||
<h2>Все функции <span class="hint">(клик по заголовку — сортировка)</span></h2>
|
<h2>Все функции <span class="hint">(клик по заголовку — сортировка)</span></h2>
|
||||||
<table id="table">
|
<table id="table">
|
||||||
<thead><tr>
|
<thead><tr>
|
||||||
@ -155,6 +166,7 @@
|
|||||||
</tr></thead>
|
</tr></thead>
|
||||||
<tbody></tbody>
|
<tbody></tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
@ -163,6 +175,6 @@
|
|||||||
<p>Загрузка данных… Если дашборд не появился — нажмите «📁 Загрузить .xlsx».</p>
|
<p>Загрузка данных… Если дашборд не появился — нажмите «📁 Загрузить .xlsx».</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="./app.js?v=10"></script>
|
<script src="./app.js?v=11"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
12
styles.css
12
styles.css
@ -75,6 +75,18 @@ main { padding: 1.5rem 2rem; display: flex; flex-direction: column; gap: 1.25rem
|
|||||||
transition: box-shadow .2s;
|
transition: box-shadow .2s;
|
||||||
}
|
}
|
||||||
.block:hover { box-shadow: 0 4px 18px rgba(96,165,250,0.10); }
|
.block:hover { box-shadow: 0 4px 18px rgba(96,165,250,0.10); }
|
||||||
|
|
||||||
|
.block.with-mascot { display: grid; grid-template-columns: 130px 1fr; gap: 1.2rem; align-items: start; }
|
||||||
|
.block.with-mascot.mascot-right { grid-template-columns: 1fr 130px; }
|
||||||
|
.block.with-mascot.mascot-right .mascot { order: 2; }
|
||||||
|
.block.with-mascot.mascot-wide { grid-template-columns: 1fr 180px; }
|
||||||
|
.block .mascot { width: 100%; max-width: 150px; align-self: center; opacity: .95; transition: transform .25s ease; }
|
||||||
|
.block .mascot:hover { transform: scale(1.06) rotate(-2deg); }
|
||||||
|
.block .block-body { min-width: 0; }
|
||||||
|
@media (max-width: 760px) {
|
||||||
|
.block.with-mascot, .block.with-mascot.mascot-right, .block.with-mascot.mascot-wide { grid-template-columns: 1fr; }
|
||||||
|
.block.with-mascot .mascot { max-width: 110px; justify-self: end; order: 0 !important; }
|
||||||
|
}
|
||||||
.block h2 {
|
.block h2 {
|
||||||
margin: 0 0 1rem;
|
margin: 0 0 1rem;
|
||||||
font-size: 1.05rem; font-weight: 700;
|
font-size: 1.05rem; font-weight: 700;
|
||||||
|
|||||||
Reference in New Issue
Block a user