Update metrics to on-time NSM and inputs

This commit is contained in:
Ruslan Bakiev
2026-02-10 17:40:47 +07:00
parent 72c8faa47d
commit c5959d5dbb

View File

@@ -150,7 +150,7 @@
</div> </div>
</section> </section>
<section id="flow" class="slide"> <section id="flow" class="slide flow-slide">
<div class="slide-top"><span class="slide-num">05</span><span class="slide-label">Key user flow</span></div> <div class="slide-top"><span class="slide-num">05</span><span class="slide-label">Key user flow</span></div>
<div class="slide-head"> <div class="slide-head">
<h2 class="slide-title">Как это работает: key user flow</h2> <h2 class="slide-title">Как это работает: key user flow</h2>
@@ -159,16 +159,13 @@
как сервис их снимает через регламент, доказуемую проверку и эскроу. как сервис их снимает через регламент, доказуемую проверку и эскроу.
</p> </p>
</div> </div>
<div class="slide-main"> <div class="slide-main flow-main">
<div class="flow-wrapper glass-panel rounded-3xl border border-base-300 p-4"> <div class="flow-wrapper glass-panel rounded-3xl border border-base-300 p-4">
<ClientOnly> <ClientOnly>
<VueFlow <VueFlow
:nodes="flowNodes" :nodes="flowNodes"
:edges="flowEdges" :edges="flowEdges"
:fit-view-on-init="false" :fit-view-on-init="true"
:default-viewport="{ x: 0, y: 0, zoom: 1 }"
:min-zoom="1"
:max-zoom="1"
:nodes-draggable="true" :nodes-draggable="true"
:nodes-connectable="false" :nodes-connectable="false"
:elements-selectable="true" :elements-selectable="true"
@@ -310,10 +307,10 @@
<div class="grid gap-6 md:grid-cols-[1fr_1fr]"> <div class="grid gap-6 md:grid-cols-[1fr_1fr]">
<div> <div>
<h3 class="font-display text-2xl">North Star Metric</h3> <h3 class="font-display text-2xl">North Star Metric</h3>
<p class="mt-3 text-sm text-neutral/70">Доля этапов, принятых с первого раза без спора.</p> <p class="mt-3 text-sm text-neutral/70">Доля этапов, выполненных в обещанный срок.</p>
<p class="mt-3 text-sm text-neutral/70"> <p class="mt-3 text-sm text-neutral/70">
Input-метрики: доля этапов с зафиксированными критериями, среднее время согласования Input-метрики: ошибка прогноза по срокам (факт минус план), отклонение объема работ от плана,
этапа, точность автосметы, доля приемок с «зеленым» статусом. фактическая длительность по типу работ (средние значения).
</p> </p>
</div> </div>
<div class="grid gap-4"> <div class="grid gap-4">
@@ -434,7 +431,7 @@ const flowNodes = ref([
{ {
id: '2', id: '2',
type: 'step', type: 'step',
position: { x: 480, y: 40 }, position: { x: 180, y: 40 },
data: { data: {
step: '02', step: '02',
title: 'Смета и этапы', title: 'Смета и этапы',
@@ -444,7 +441,7 @@ const flowNodes = ref([
{ {
id: '3', id: '3',
type: 'step', type: 'step',
position: { x: 960, y: 40 }, position: { x: 360, y: 40 },
data: { data: {
step: '03', step: '03',
title: 'Создание заявки', title: 'Создание заявки',
@@ -454,7 +451,7 @@ const flowNodes = ref([
{ {
id: '4', id: '4',
type: 'step', type: 'step',
position: { x: 1440, y: 40 }, position: { x: 540, y: 40 },
data: { data: {
step: '04', step: '04',
title: 'Выбор исполнителя', title: 'Выбор исполнителя',
@@ -464,7 +461,7 @@ const flowNodes = ref([
{ {
id: '5', id: '5',
type: 'step', type: 'step',
position: { x: 1920, y: 40 }, position: { x: 720, y: 40 },
data: { data: {
step: '05', step: '05',
title: 'Эскроу и запуск', title: 'Эскроу и запуск',
@@ -474,7 +471,7 @@ const flowNodes = ref([
{ {
id: '6', id: '6',
type: 'step', type: 'step',
position: { x: 2400, y: 40 }, position: { x: 900, y: 40 },
data: { data: {
step: '06', step: '06',
title: 'Фиксация прогресса', title: 'Фиксация прогресса',
@@ -484,7 +481,7 @@ const flowNodes = ref([
{ {
id: '7', id: '7',
type: 'step', type: 'step',
position: { x: 2880, y: 40 }, position: { x: 1080, y: 40 },
data: { data: {
step: '07', step: '07',
title: 'Приемка и расчет', title: 'Приемка и расчет',
@@ -494,12 +491,12 @@ const flowNodes = ref([
]) ])
const flowEdges = ref([ const flowEdges = ref([
{ id: 'e1-2', source: '1', target: '2', sourceHandle: 'source-r', targetHandle: 'target-l', type: 'smoothstep', markerEnd: MarkerType.ArrowClosed }, { id: 'e1-2', source: '1', target: '2', sourceHandle: 'source-r', targetHandle: 'target-l', type: 'straight', markerEnd: MarkerType.ArrowClosed },
{ id: 'e2-3', source: '2', target: '3', sourceHandle: 'source-r', targetHandle: 'target-l', type: 'smoothstep', markerEnd: MarkerType.ArrowClosed }, { id: 'e2-3', source: '2', target: '3', sourceHandle: 'source-r', targetHandle: 'target-l', type: 'straight', markerEnd: MarkerType.ArrowClosed },
{ id: 'e3-4', source: '3', target: '4', sourceHandle: 'source-r', targetHandle: 'target-l', type: 'smoothstep', markerEnd: MarkerType.ArrowClosed }, { id: 'e3-4', source: '3', target: '4', sourceHandle: 'source-r', targetHandle: 'target-l', type: 'straight', markerEnd: MarkerType.ArrowClosed },
{ id: 'e4-5', source: '4', target: '5', sourceHandle: 'source-r', targetHandle: 'target-l', type: 'smoothstep', markerEnd: MarkerType.ArrowClosed }, { id: 'e4-5', source: '4', target: '5', sourceHandle: 'source-r', targetHandle: 'target-l', type: 'straight', markerEnd: MarkerType.ArrowClosed },
{ id: 'e5-6', source: '5', target: '6', sourceHandle: 'source-r', targetHandle: 'target-l', type: 'smoothstep', markerEnd: MarkerType.ArrowClosed }, { id: 'e5-6', source: '5', target: '6', sourceHandle: 'source-r', targetHandle: 'target-l', type: 'straight', markerEnd: MarkerType.ArrowClosed },
{ id: 'e6-7', source: '6', target: '7', sourceHandle: 'source-r', targetHandle: 'target-l', type: 'smoothstep', markerEnd: MarkerType.ArrowClosed } { id: 'e6-7', source: '6', target: '7', sourceHandle: 'source-r', targetHandle: 'target-l', type: 'straight', markerEnd: MarkerType.ArrowClosed }
]) ])
onMounted(() => { onMounted(() => {
@@ -557,10 +554,11 @@ html {
.flow-wrapper { .flow-wrapper {
width: 100%; width: 100%;
height: 280px; height: 100%;
overflow-x: auto; overflow-x: auto;
overflow-y: hidden; overflow-y: hidden;
scrollbar-width: thin; scrollbar-width: thin;
position: relative;
} }
.flow-wrapper::-webkit-scrollbar { .flow-wrapper::-webkit-scrollbar {
@@ -582,9 +580,27 @@ html {
height: 100%; height: 100%;
} }
.vue-flow {
position: relative;
}
.vue-flow__nodes {
position: absolute;
top: 0;
left: 0;
}
.vue-flow__edges {
position: absolute;
inset: 0;
}
.flow-card { .flow-card {
min-width: 200px; min-width: 160px;
max-width: 220px; max-width: 160px;
background: rgba(255, 255, 255, 0.78);
border: 1px solid rgba(20, 20, 20, 0.12);
box-shadow: 0 14px 30px rgba(20, 20, 20, 0.14);
} }
.flow-handle { .flow-handle {
@@ -699,6 +715,16 @@ html {
gap: 1.5rem; gap: 1.5rem;
} }
.flow-slide .slide-main {
flex: 1;
min-height: 420px;
}
.flow-main .flow-wrapper {
height: 100%;
min-height: 420px;
}
.glass-panel { .glass-panel {
background: rgba(255, 255, 255, 0.55); background: rgba(255, 255, 255, 0.55);
border: 1px solid rgba(255, 255, 255, 0.5); border: 1px solid rgba(255, 255, 255, 0.5);
@@ -732,6 +758,12 @@ html {
-webkit-backdrop-filter: blur(16px) saturate(1.05); -webkit-backdrop-filter: blur(16px) saturate(1.05);
} }
.flow-card.glass-card {
background: rgba(255, 255, 255, 0.78);
border: 1px solid rgba(20, 20, 20, 0.12);
box-shadow: 0 14px 30px rgba(20, 20, 20, 0.14);
}
.iphone-frame { .iphone-frame {
position: relative; position: relative;
width: min(330px, 90vw); width: min(330px, 90vw);
@@ -774,12 +806,12 @@ html {
.iphone-notch { .iphone-notch {
position: absolute; position: absolute;
top: 10px; top: 0;
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
width: 46%; width: 42%;
height: 24px; height: 26px;
border-radius: 0 0 18px 18px; border-radius: 0 0 20px 20px;
background: #0b0b0e; background: #0b0b0e;
box-shadow: 0 6px 10px rgba(0, 0, 0, 0.35); box-shadow: 0 6px 10px rgba(0, 0, 0, 0.35);
z-index: 2; z-index: 2;