Update roadmap to 3-phase 6-month plan

This commit is contained in:
Ruslan Bakiev
2026-02-10 17:00:56 +07:00
parent 27dc375f33
commit ac6e06f4c5
4 changed files with 410 additions and 28 deletions

View File

@@ -1,5 +1,6 @@
<template> <template>
<div data-theme="silk" class="min-h-screen bg-mesh text-neutral"> <div data-theme="silk" class="min-h-screen bg-mesh text-neutral">
<canvas id="canvas-basic" class="gradient-canvas" aria-hidden="true"></canvas>
<div class="relative z-10"> <div class="relative z-10">
<div <div
class="pointer-events-none absolute -top-24 left-1/2 h-72 w-[1100px] -translate-x-1/2 rounded-full bg-[radial-gradient(circle_at_center,rgba(67,56,118,0.25),transparent_70%)] blur-3xl" class="pointer-events-none absolute -top-24 left-1/2 h-72 w-[1100px] -translate-x-1/2 rounded-full bg-[radial-gradient(circle_at_center,rgba(67,56,118,0.25),transparent_70%)] blur-3xl"
@@ -159,28 +160,35 @@
</p> </p>
</div> </div>
<div class="slide-main"> <div class="slide-main">
<div class="grid gap-6 md:grid-cols-3"> <div class="flow-wrapper glass-panel rounded-3xl border border-base-300 p-4">
<div class="glass-card rounded-3xl p-6 shadow-soft"> <ClientOnly>
<h3 class="font-display text-2xl">Старт проекта</h3> <VueFlow
<p class="mt-3 text-sm text-neutral/70"> :nodes="flowNodes"
Заказчик добавляет объект (фото/видео/обмеры), получает смету, этапы и критерии. Точка :edges="flowEdges"
трения снимается заранее: все ожидают одинаковый результат. :fit-view-on-init="true"
</p> :nodes-draggable="false"
</div> :nodes-connectable="false"
<div class="glass-card rounded-3xl p-6 shadow-soft"> :elements-selectable="false"
<h3 class="font-display text-2xl">Ведение этапа</h3> :zoom-on-scroll="false"
<p class="mt-3 text-sm text-neutral/70"> :zoom-on-pinch="false"
Исполнитель работает по регламенту и чек-листам, прогресс фиксируется. Заказчик видит :pan-on-drag="false"
прозрачный статус без переписки. :pan-on-scroll="false"
</p> >
</div> <template #node-step="{ data }">
<div class="glass-card rounded-3xl p-6 shadow-soft"> <div class="flow-card glass-card rounded-3xl p-5 shadow-soft">
<h3 class="font-display text-2xl">Приемка и расчет</h3> <div class="text-xs font-semibold text-neutral/60">{{ data.step }}</div>
<p class="mt-3 text-sm text-neutral/70"> <div class="mt-2 font-display text-lg">{{ data.title }}</div>
Независимый инспектор сверяет критерии, сервис фиксирует решение и переводит эскроу. <div class="mt-3 text-sm text-neutral/70">{{ data.text }}</div>
Спор заменяется фактами. <Handle id="target-l" type="target" :position="Position.Left" class="flow-handle" />
</p> <Handle id="target-r" type="target" :position="Position.Right" class="flow-handle" />
<Handle id="target-t" type="target" :position="Position.Top" class="flow-handle" />
<Handle id="source-r" type="source" :position="Position.Right" class="flow-handle" />
<Handle id="source-l" type="source" :position="Position.Left" class="flow-handle" />
<Handle id="source-b" type="source" :position="Position.Bottom" class="flow-handle" />
</div> </div>
</template>
</VueFlow>
</ClientOnly>
</div> </div>
</div> </div>
</section> </section>
@@ -326,10 +334,10 @@
<section id="roadmap" class="slide"> <section id="roadmap" class="slide">
<div class="slide-top"><span class="slide-num">10</span><span class="slide-label">Roadmap</span></div> <div class="slide-top"><span class="slide-num">10</span><span class="slide-label">Roadmap</span></div>
<div class="slide-head"> <div class="slide-head">
<h2 class="slide-title">От пилота к системе приемки</h2> <h2 class="slide-title">Пилот за 2 месяца, затем смета и приемка</h2>
<p class="slide-preamble"> <p class="slide-preamble">
Сначала проверяем гипотезы на реальных ремонтах, затем усиливаем расчет ресурсов и выносим Первые два месяца уходит на запуск пилота: этапы работ, декомпозиция объема и подбор исполнителей.
независимую приемку как масштабируемый сервис. Затем доводим ресурсную ведомость и смету, а в конце выстраиваем приемку с инспекторами.
</p> </p>
</div> </div>
<div class="slide-main"> <div class="slide-main">
@@ -346,7 +354,7 @@
</div> </div>
<div class="grid grid-cols-[160px_repeat(6,minmax(0,1fr))] items-center gap-2"> <div class="grid grid-cols-[160px_repeat(6,minmax(0,1fr))] items-center gap-2">
<div class="text-neutral/70">Пилот на ремонтах</div> <div class="text-neutral/70">Пилот: этапы, объем, исполнители</div>
<div class="rounded-full bg-primary py-2 text-center text-xs text-primary-content">М1</div> <div class="rounded-full bg-primary py-2 text-center text-xs text-primary-content">М1</div>
<div class="rounded-full bg-primary py-2 text-center text-xs text-primary-content">М2</div> <div class="rounded-full bg-primary py-2 text-center text-xs text-primary-content">М2</div>
<div class="rounded-full bg-base-300/70 py-2"></div> <div class="rounded-full bg-base-300/70 py-2"></div>
@@ -356,7 +364,7 @@
</div> </div>
<div class="grid grid-cols-[160px_repeat(6,minmax(0,1fr))] items-center gap-2"> <div class="grid grid-cols-[160px_repeat(6,minmax(0,1fr))] items-center gap-2">
<div class="text-neutral/70">Расчет ресурсной сметы</div> <div class="text-neutral/70">Ресурсная ведомость и смета</div>
<div class="rounded-full bg-base-300/70 py-2"></div> <div class="rounded-full bg-base-300/70 py-2"></div>
<div class="rounded-full bg-base-300/70 py-2"></div> <div class="rounded-full bg-base-300/70 py-2"></div>
<div class="rounded-full bg-primary py-2 text-center text-xs text-primary-content">М3</div> <div class="rounded-full bg-primary py-2 text-center text-xs text-primary-content">М3</div>
@@ -366,7 +374,7 @@
</div> </div>
<div class="grid grid-cols-[160px_repeat(6,minmax(0,1fr))] items-center gap-2"> <div class="grid grid-cols-[160px_repeat(6,minmax(0,1fr))] items-center gap-2">
<div class="text-neutral/70">Инспектор и приемка</div> <div class="text-neutral/70">Приемка и инспекторы</div>
<div class="rounded-full bg-base-300/70 py-2"></div> <div class="rounded-full bg-base-300/70 py-2"></div>
<div class="rounded-full bg-base-300/70 py-2"></div> <div class="rounded-full bg-base-300/70 py-2"></div>
<div class="rounded-full bg-base-300/70 py-2"></div> <div class="rounded-full bg-base-300/70 py-2"></div>
@@ -405,6 +413,9 @@
</template> </template>
<script setup> <script setup>
import { onMounted, onUnmounted, ref } from 'vue'
import { VueFlow, Handle, Position, MarkerType } from '@vue-flow/core'
import Granim from 'granim'
useHead({ useHead({
title: 'Контроль ремонта — презентация', title: 'Контроль ремонта — презентация',
@@ -412,9 +423,115 @@ useHead({
{ name: 'description', content: 'Презентация продукта: смета, приемка, эскроу и методология ремонта.' } { name: 'description', content: 'Презентация продукта: смета, приемка, эскроу и методология ремонта.' }
] ]
}) })
let granimInstance
const flowNodes = ref([
{
id: '1',
type: 'step',
position: { x: 0, y: 40 },
data: {
step: '01',
title: 'Добавление объекта',
text: 'Заказчик загружает фото/видео/обмеры или проект — система получает исходные данные.'
}
},
{
id: '2',
type: 'step',
position: { x: 240, y: 40 },
data: {
step: '02',
title: 'Смета и этапы',
text: 'Алгоритм формирует объем работ, смету, этапы и критерии приемки по каждому шагу.'
}
},
{
id: '3',
type: 'step',
position: { x: 480, y: 40 },
data: {
step: '03',
title: 'Создание заявки',
text: 'Заказчик подтверждает параметры и публикует заявку на выполнение работ.'
}
},
{
id: '4',
type: 'step',
position: { x: 720, y: 40 },
data: {
step: '04',
title: 'Выбор исполнителя',
text: 'Выбирается бригада или мастер, согласуются сроки и старт этапа.'
}
},
{
id: '5',
type: 'step',
position: { x: 720, y: 220 },
data: {
step: '05',
title: 'Эскроу и запуск',
text: 'Заказчик вносит оплату в эскроу, исполнитель запускает работы по регламенту.'
}
},
{
id: '6',
type: 'step',
position: { x: 480, y: 220 },
data: {
step: '06',
title: 'Фиксация прогресса',
text: 'Исполнитель ведет этапы, отмечает завершение, заказчик видит статус и результаты.'
}
},
{
id: '7',
type: 'step',
position: { x: 240, y: 220 },
data: {
step: '07',
title: 'Приемка и расчет',
text: 'Инспектор сверяет критерии: если все ок — эскроу разблокируется, если нет — доработка или удержание.'
}
}
])
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-b', targetHandle: 'target-t', type: 'smoothstep', markerEnd: MarkerType.ArrowClosed },
{ id: 'e5-6', source: '5', target: '6', sourceHandle: 'source-l', targetHandle: 'target-r', type: 'smoothstep', markerEnd: MarkerType.ArrowClosed },
{ id: 'e6-7', source: '6', target: '7', sourceHandle: 'source-l', targetHandle: 'target-r', type: 'smoothstep', markerEnd: MarkerType.ArrowClosed }
])
onMounted(() => {
granimInstance = new Granim({
element: '#canvas-basic',
direction: 'radial',
isPausedWhenNotInView: true,
states: {
'default-state': {
gradients: [
['#ff9966', '#ff5e62'],
['#00F260', '#0575E6'],
['#e1eec3', '#f05053']
]
}
}
})
onUnmounted(() => {
if (granimInstance && granimInstance.pause) granimInstance.pause()
})
})
</script> </script>
<style> <style>
@import '@vue-flow/core/dist/style.css';
@import '@vue-flow/core/dist/theme-default.css';
@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@300;400;600;700&family=Space+Grotesk:wght@400;600;700&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Manrope:wght@300;400;600;700&family=Space+Grotesk:wght@400;600;700&display=swap');
:root { :root {
@@ -433,6 +550,45 @@ html {
font-family: 'Space Grotesk', system-ui, sans-serif; font-family: 'Space Grotesk', system-ui, sans-serif;
} }
.gradient-canvas {
position: fixed;
inset: 0;
width: 100%;
height: 100%;
z-index: 0;
pointer-events: none;
filter: saturate(1.1);
}
.flow-wrapper {
width: 100%;
height: 420px;
overflow: hidden;
}
.flow-wrapper .vue-flow {
width: 100%;
height: 100%;
}
.flow-card {
min-width: 200px;
max-width: 220px;
}
.flow-handle {
opacity: 0;
}
.vue-flow__edge-path {
stroke: rgba(20, 20, 20, 0.45);
stroke-width: 1.4;
}
.vue-flow__edge-marker path {
fill: rgba(20, 20, 20, 0.6);
}
.nav-link { .nav-link {
transition: all 0.2s ease; transition: all 0.2s ease;
display: flex; display: flex;

224
package-lock.json generated
View File

@@ -8,6 +8,8 @@
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"@nuxtjs/tailwindcss": "^6.14.0", "@nuxtjs/tailwindcss": "^6.14.0",
"@vue-flow/core": "^1.48.2",
"granim": "^2.0.0",
"nuxt": "^4.3.1", "nuxt": "^4.3.1",
"vue": "^3.5.28", "vue": "^3.5.28",
"vue-router": "^4.6.4" "vue-router": "^4.6.4"
@@ -3562,6 +3564,12 @@
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/web-bluetooth": {
"version": "0.0.20",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
"integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==",
"license": "MIT"
},
"node_modules/@unhead/vue": { "node_modules/@unhead/vue": {
"version": "2.1.4", "version": "2.1.4",
"resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-2.1.4.tgz", "resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-2.1.4.tgz",
@@ -3661,6 +3669,22 @@
"integrity": "sha512-ynlcBReMgOZj2i6po+qVswtDUeeBRCTgDurjMGShbm8WYZgJ0PA4RmtebBJ0BCYol1qPv3GQF6jK7C9qoVc7lg==", "integrity": "sha512-ynlcBReMgOZj2i6po+qVswtDUeeBRCTgDurjMGShbm8WYZgJ0PA4RmtebBJ0BCYol1qPv3GQF6jK7C9qoVc7lg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@vue-flow/core": {
"version": "1.48.2",
"resolved": "https://registry.npmjs.org/@vue-flow/core/-/core-1.48.2.tgz",
"integrity": "sha512-raxhgKWE+G/mcEvXJjGFUDYW9rAI3GOtiHR3ZkNpwBWuIaCC1EYiBmKGwJOoNzVFgwO7COgErnK7i08i287AFA==",
"license": "MIT",
"dependencies": {
"@vueuse/core": "^10.5.0",
"d3-drag": "^3.0.0",
"d3-interpolate": "^3.0.1",
"d3-selection": "^3.0.0",
"d3-zoom": "^3.0.0"
},
"peerDependencies": {
"vue": "^3.3.0"
}
},
"node_modules/@vue-macros/common": { "node_modules/@vue-macros/common": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue-macros/common/-/common-3.1.2.tgz", "resolved": "https://registry.npmjs.org/@vue-macros/common/-/common-3.1.2.tgz",
@@ -3917,6 +3941,94 @@
"integrity": "sha512-cfWa1fCGBxrvaHRhvV3Is0MgmrbSCxYTXCSCau2I0a1Xw1N1pHAvkWCiXPRAqjvToILvguNyEwjevUqAuBQWvQ==", "integrity": "sha512-cfWa1fCGBxrvaHRhvV3Is0MgmrbSCxYTXCSCau2I0a1Xw1N1pHAvkWCiXPRAqjvToILvguNyEwjevUqAuBQWvQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@vueuse/core": {
"version": "10.11.1",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.1.tgz",
"integrity": "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==",
"license": "MIT",
"dependencies": {
"@types/web-bluetooth": "^0.0.20",
"@vueuse/metadata": "10.11.1",
"@vueuse/shared": "10.11.1",
"vue-demi": ">=0.14.8"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@vueuse/metadata": {
"version": "10.11.1",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.1.tgz",
"integrity": "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
"version": "10.11.1",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.1.tgz",
"integrity": "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==",
"license": "MIT",
"dependencies": {
"vue-demi": ">=0.14.8"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/abbrev": { "node_modules/abbrev": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz",
@@ -5181,6 +5293,112 @@
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/d3-color": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
"integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
"license": "ISC",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-dispatch": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
"integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
"license": "ISC",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-drag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz",
"integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
"license": "ISC",
"dependencies": {
"d3-dispatch": "1 - 3",
"d3-selection": "3"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-ease": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
"integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-interpolate": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
"integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
"license": "ISC",
"dependencies": {
"d3-color": "1 - 3"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-selection": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
"license": "ISC",
"peer": true,
"engines": {
"node": ">=12"
}
},
"node_modules/d3-timer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
"integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
"license": "ISC",
"engines": {
"node": ">=12"
}
},
"node_modules/d3-transition": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz",
"integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
"license": "ISC",
"dependencies": {
"d3-color": "1 - 3",
"d3-dispatch": "1 - 3",
"d3-ease": "1 - 3",
"d3-interpolate": "1 - 3",
"d3-timer": "1 - 3"
},
"engines": {
"node": ">=12"
},
"peerDependencies": {
"d3-selection": "2 - 3"
}
},
"node_modules/d3-zoom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz",
"integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==",
"license": "ISC",
"dependencies": {
"d3-dispatch": "1 - 3",
"d3-drag": "2 - 3",
"d3-interpolate": "1 - 3",
"d3-selection": "2 - 3",
"d3-transition": "2 - 3"
},
"engines": {
"node": ">=12"
}
},
"node_modules/daisyui": { "node_modules/daisyui": {
"version": "5.5.18", "version": "5.5.18",
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.5.18.tgz", "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.5.18.tgz",
@@ -6070,6 +6288,12 @@
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/granim": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/granim/-/granim-2.0.0.tgz",
"integrity": "sha512-aqa79K49ndjoUBtpYzlO8sKcuVQED+5axvX0SveqTLDR+Fa2G42AGntuQ36ysCFOWGVkWCLfHowFwk+D/9rGDg==",
"license": "MIT"
},
"node_modules/gzip-size": { "node_modules/gzip-size": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-7.0.0.tgz", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-7.0.0.tgz",

View File

@@ -11,6 +11,8 @@
}, },
"dependencies": { "dependencies": {
"@nuxtjs/tailwindcss": "^6.14.0", "@nuxtjs/tailwindcss": "^6.14.0",
"@vue-flow/core": "^1.48.2",
"granim": "^2.0.0",
"nuxt": "^4.3.1", "nuxt": "^4.3.1",
"vue": "^3.5.28", "vue": "^3.5.28",
"vue-router": "^4.6.4" "vue-router": "^4.6.4"

BIN
public/avatar.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB