Update metrics to on-time NSM and inputs
This commit is contained in:
88
app/app.vue
88
app/app.vue
@@ -150,7 +150,7 @@
|
||||
</div>
|
||||
</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-head">
|
||||
<h2 class="slide-title">Как это работает: key user flow</h2>
|
||||
@@ -159,16 +159,13 @@
|
||||
как сервис их снимает — через регламент, доказуемую проверку и эскроу.
|
||||
</p>
|
||||
</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">
|
||||
<ClientOnly>
|
||||
<VueFlow
|
||||
:nodes="flowNodes"
|
||||
:edges="flowEdges"
|
||||
:fit-view-on-init="false"
|
||||
:default-viewport="{ x: 0, y: 0, zoom: 1 }"
|
||||
:min-zoom="1"
|
||||
:max-zoom="1"
|
||||
:fit-view-on-init="true"
|
||||
:nodes-draggable="true"
|
||||
:nodes-connectable="false"
|
||||
:elements-selectable="true"
|
||||
@@ -310,10 +307,10 @@
|
||||
<div class="grid gap-6 md:grid-cols-[1fr_1fr]">
|
||||
<div>
|
||||
<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">
|
||||
Input-метрики: доля этапов с зафиксированными критериями, среднее время согласования
|
||||
этапа, точность автосметы, доля приемок с «зеленым» статусом.
|
||||
Input-метрики: ошибка прогноза по срокам (факт минус план), отклонение объема работ от плана,
|
||||
фактическая длительность по типу работ (средние значения).
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid gap-4">
|
||||
@@ -434,7 +431,7 @@ const flowNodes = ref([
|
||||
{
|
||||
id: '2',
|
||||
type: 'step',
|
||||
position: { x: 480, y: 40 },
|
||||
position: { x: 180, y: 40 },
|
||||
data: {
|
||||
step: '02',
|
||||
title: 'Смета и этапы',
|
||||
@@ -444,7 +441,7 @@ const flowNodes = ref([
|
||||
{
|
||||
id: '3',
|
||||
type: 'step',
|
||||
position: { x: 960, y: 40 },
|
||||
position: { x: 360, y: 40 },
|
||||
data: {
|
||||
step: '03',
|
||||
title: 'Создание заявки',
|
||||
@@ -454,7 +451,7 @@ const flowNodes = ref([
|
||||
{
|
||||
id: '4',
|
||||
type: 'step',
|
||||
position: { x: 1440, y: 40 },
|
||||
position: { x: 540, y: 40 },
|
||||
data: {
|
||||
step: '04',
|
||||
title: 'Выбор исполнителя',
|
||||
@@ -464,7 +461,7 @@ const flowNodes = ref([
|
||||
{
|
||||
id: '5',
|
||||
type: 'step',
|
||||
position: { x: 1920, y: 40 },
|
||||
position: { x: 720, y: 40 },
|
||||
data: {
|
||||
step: '05',
|
||||
title: 'Эскроу и запуск',
|
||||
@@ -474,7 +471,7 @@ const flowNodes = ref([
|
||||
{
|
||||
id: '6',
|
||||
type: 'step',
|
||||
position: { x: 2400, y: 40 },
|
||||
position: { x: 900, y: 40 },
|
||||
data: {
|
||||
step: '06',
|
||||
title: 'Фиксация прогресса',
|
||||
@@ -484,7 +481,7 @@ const flowNodes = ref([
|
||||
{
|
||||
id: '7',
|
||||
type: 'step',
|
||||
position: { x: 2880, y: 40 },
|
||||
position: { x: 1080, y: 40 },
|
||||
data: {
|
||||
step: '07',
|
||||
title: 'Приемка и расчет',
|
||||
@@ -494,12 +491,12 @@ const flowNodes = ref([
|
||||
])
|
||||
|
||||
const flowEdges = ref([
|
||||
{ id: 'e1-2', source: '1', target: '2', 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: 'smoothstep', markerEnd: MarkerType.ArrowClosed },
|
||||
{ id: 'e3-4', source: '3', target: '4', 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: 'smoothstep', markerEnd: MarkerType.ArrowClosed },
|
||||
{ id: 'e5-6', source: '5', target: '6', 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: '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: 'straight', 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: 'straight', 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: 'straight', markerEnd: MarkerType.ArrowClosed }
|
||||
])
|
||||
|
||||
onMounted(() => {
|
||||
@@ -557,10 +554,11 @@ html {
|
||||
|
||||
.flow-wrapper {
|
||||
width: 100%;
|
||||
height: 280px;
|
||||
height: 100%;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
scrollbar-width: thin;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.flow-wrapper::-webkit-scrollbar {
|
||||
@@ -582,9 +580,27 @@ html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.vue-flow {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.vue-flow__nodes {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.vue-flow__edges {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
}
|
||||
|
||||
.flow-card {
|
||||
min-width: 200px;
|
||||
max-width: 220px;
|
||||
min-width: 160px;
|
||||
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 {
|
||||
@@ -699,6 +715,16 @@ html {
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.flow-slide .slide-main {
|
||||
flex: 1;
|
||||
min-height: 420px;
|
||||
}
|
||||
|
||||
.flow-main .flow-wrapper {
|
||||
height: 100%;
|
||||
min-height: 420px;
|
||||
}
|
||||
|
||||
.glass-panel {
|
||||
background: rgba(255, 255, 255, 0.55);
|
||||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||
@@ -732,6 +758,12 @@ html {
|
||||
-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 {
|
||||
position: relative;
|
||||
width: min(330px, 90vw);
|
||||
@@ -774,12 +806,12 @@ html {
|
||||
|
||||
.iphone-notch {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 46%;
|
||||
height: 24px;
|
||||
border-radius: 0 0 18px 18px;
|
||||
width: 42%;
|
||||
height: 26px;
|
||||
border-radius: 0 0 20px 20px;
|
||||
background: #0b0b0e;
|
||||
box-shadow: 0 6px 10px rgba(0, 0, 0, 0.35);
|
||||
z-index: 2;
|
||||
|
||||
Reference in New Issue
Block a user