diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..56281c0
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+cd frontend && npm run build && cd ..
+rm -rf cmd/verstak-gui/frontend-dist && cp -r frontend/dist cmd/verstak-gui/frontend-dist
+go build -tags "gui production webkit2_41" -o verstak-gui ./cmd/verstak-gui
diff --git a/cmd/verstak-gui/app.go b/cmd/verstak-gui/app.go
index 018a93f..6848108 100644
--- a/cmd/verstak-gui/app.go
+++ b/cmd/verstak-gui/app.go
@@ -5,6 +5,7 @@ import (
"fmt"
"os"
"os/exec"
+ "path/filepath"
"strings"
wailsruntime "github.com/wailsapp/wails/v2/pkg/runtime"
@@ -13,6 +14,7 @@ import (
"verstak/internal/core/files"
"verstak/internal/core/notes"
"verstak/internal/core/nodes"
+ "verstak/internal/core/search"
"verstak/internal/core/storage"
"verstak/internal/core/worklog"
)
@@ -26,6 +28,7 @@ type App struct {
notes *notes.Service
actions *actions.Service
worklog *worklog.Service
+ search *search.Service
vault string
}
@@ -296,14 +299,27 @@ func (a *App) CreateWorklog(nodeID, summary string, minutes int) (*WorklogDTO, e
}
// ============================================================
-// Search (stubs — search service not wired yet)
+// Search
// ============================================================
func (a *App) Search(query string) ([]SearchResultDTO, error) {
if strings.TrimSpace(query) == "" {
return []SearchResultDTO{}, nil
}
- return []SearchResultDTO{}, nil
+ results, err := a.search.Search(query)
+ if err != nil {
+ return nil, err
+ }
+ out := make([]SearchResultDTO, len(results))
+ for i, r := range results {
+ out[i] = SearchResultDTO{
+ NodeID: r.NodeID,
+ Title: r.Title,
+ Snippet: r.Snippet,
+ Type: r.Type,
+ }
+ }
+ return out, nil
}
// ============================================================
@@ -333,11 +349,19 @@ func (a *App) PickDirectory() (string, error) {
// ============================================================
func (a *App) OpenFile(fileID string) error {
- return fmt.Errorf("not implemented: %s", fileID)
+ return a.files.Open(fileID)
}
func (a *App) OpenFolder(nodeID string) error {
- cmd := exec.Command("xdg-open", a.vault)
+ n, err := a.nodes.GetActive(nodeID)
+ if err != nil {
+ return fmt.Errorf("get node: %w", err)
+ }
+ dir := filepath.Join(a.vault, "spaces", n.Slug)
+ if _, err := os.Stat(dir); os.IsNotExist(err) {
+ dir = a.vault
+ }
+ cmd := exec.Command("xdg-open", dir)
return cmd.Run()
}
@@ -377,7 +401,4 @@ func toNodeDTOs(list []nodes.Node) []NodeDTO {
return result
}
-var (
- _ = os.Getenv
- _ = exec.Command
-)
+
diff --git a/cmd/verstak-gui/frontend-dist/assets/index-COs6tJEl.js b/cmd/verstak-gui/frontend-dist/assets/index-COs6tJEl.js
deleted file mode 100644
index b95e9a9..0000000
--- a/cmd/verstak-gui/frontend-dist/assets/index-COs6tJEl.js
+++ /dev/null
@@ -1 +0,0 @@
-var Ae=Object.defineProperty;var Ne=(t,e,l)=>e in t?Ae(t,e,{enumerable:!0,configurable:!0,writable:!0,value:l}):t[e]=l;var ee=(t,e,l)=>Ne(t,typeof e!="symbol"?e+"":e,l);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))n(s);new MutationObserver(s=>{for(const i of s)if(i.type==="childList")for(const o of i.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&n(o)}).observe(document,{childList:!0,subtree:!0});function l(s){const i={};return s.integrity&&(i.integrity=s.integrity),s.referrerPolicy&&(i.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?i.credentials="include":s.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function n(s){if(s.ep)return;s.ep=!0;const i=l(s);fetch(s.href,i)}})();function B(){}function we(t){return t()}function fe(){return Object.create(null)}function Z(t){t.forEach(we)}function $e(t){return typeof t=="function"}function Oe(t,e){return t!=t?e==e:t!==e||t&&typeof t=="object"||typeof t=="function"}function Ce(t){return Object.keys(t).length===0}function c(t,e){t.appendChild(e)}function N(t,e,l){t.insertBefore(e,l||null)}function L(t){t.parentNode&&t.parentNode.removeChild(t)}function le(t,e){for(let l=0;lt.removeEventListener(e,l,n)}function a(t,e,l){l==null?t.removeAttribute(e):t.getAttribute(e)!==l&&t.setAttribute(e,l)}function Se(t){return Array.from(t.childNodes)}function S(t,e){e=""+e,t.data!==e&&(t.data=e)}let J;function W(t){J=t}function Pe(){if(!J)throw new Error("Function called outside component initialization");return J}function Ie(t){Pe().$$.on_mount.push(t)}const q=[],ae=[];let D=[];const de=[],Me=Promise.resolve();let ne=!1;function je(){ne||(ne=!0,Me.then(Le))}function se(t){D.push(t)}const te=new Set;let R=0;function Le(){if(R!==0)return;const t=J;do{try{for(;Rt.indexOf(n)===-1?e.push(n):l.push(n)),l.forEach(n=>n()),D=e}const Ve=new Set;function Fe(t,e){t&&t.i&&(Ve.delete(t),t.i(e))}function z(t){return(t==null?void 0:t.length)!==void 0?t:Array.from(t)}function He(t,e,l){const{fragment:n,after_update:s}=t.$$;n&&n.m(e,l),se(()=>{const i=t.$$.on_mount.map(we).filter($e);t.$$.on_destroy?t.$$.on_destroy.push(...i):Z(i),t.$$.on_mount=[]}),s.forEach(se)}function Re(t,e){const l=t.$$;l.fragment!==null&&(Be(l.after_update),Z(l.on_destroy),l.fragment&&l.fragment.d(e),l.on_destroy=l.fragment=null,l.ctx=[])}function qe(t,e){t.$$.dirty[0]===-1&&(q.push(t),je(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{const b=h.length?h[0]:v;return u.ctx&&s(u.ctx[g],u.ctx[g]=b)&&(!u.skip_bound&&u.bound[g]&&u.bound[g](b),_&&qe(t,g)),v}):[],u.update(),_=!0,Z(u.before_update),u.fragment=n?n(u.ctx):!1,e.target){if(e.hydrate){const g=Se(e.target);u.fragment&&u.fragment.l(g),g.forEach(L)}else u.fragment&&u.fragment.c();e.intro&&Fe(t.$$.fragment),He(t,e.target,e.anchor),Le()}W(m)}class De{constructor(){ee(this,"$$");ee(this,"$$set")}$destroy(){Re(this,1),this.$destroy=B}$on(e,l){if(!$e(l))return B;const n=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return n.push(l),()=>{const s=n.indexOf(l);s!==-1&&n.splice(s,1)}}$set(e){this.$$set&&!Ce(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}}const Ge="4";typeof window<"u"&&(window.__svelte||(window.__svelte={v:new Set})).v.add(Ge);function _e(t,e,l){const n=t.slice();return n[10]=e[l],n}function he(t,e,l){const n=t.slice();return n[13]=e[l],n}function pe(t,e,l){const n=t.slice();return n[10]=e[l],n}function ve(t){let e,l=t[10].label+"",n,s,i,o,p;function m(){return t[8](t[10])}return{c(){e=d("button"),n=k(l),s=$(),a(e,"class",i="nav-item "+(t[4]===t[10].id?"selected":"")+" svelte-14ysusk")},m(u,_){N(u,e,_),c(e,n),c(e,s),o||(p=Ee(e,"click",m),o=!0)},p(u,_){t=u,_&1&&l!==(l=t[10].label+"")&&S(n,l),_&17&&i!==(i="nav-item "+(t[4]===t[10].id?"selected":"")+" svelte-14ysusk")&&a(e,"class",i)},d(u){u&&L(e),o=!1,p()}}}function me(t){let e,l=t[13].title+"",n,s,i,o;function p(){return t[9](t[13])}return{c(){e=d("button"),n=k(l),a(e,"class",s="nav-item "+(t[5]&&t[5].id===t[13].id?"selected":"")+" svelte-14ysusk")},m(m,u){N(m,e,u),c(e,n),i||(o=Ee(e,"click",p),i=!0)},p(m,u){t=m,u&2&&l!==(l=t[13].title+"")&&S(n,l),u&34&&s!==(s="nav-item "+(t[5]&&t[5].id===t[13].id?"selected":"")+" svelte-14ysusk")&&a(e,"class",s)},d(m){m&&L(e),i=!1,o()}}}function ge(t){let e;return{c(){e=d("div"),e.textContent="Нет дел",a(e,"class","nav-empty svelte-14ysusk")},m(l,n){N(l,e,n)},d(l){l&&L(e)}}}function Ke(t){let e;return{c(){e=d("span"),e.textContent="Выберите раздел или дело",a(e,"class","crumb placeholder svelte-14ysusk")},m(l,n){N(l,e,n)},p:B,d(l){l&&L(e)}}}function Ue(t){let e,l=z(t[0]),n=[];for(let s=0;s0&&ge();function re(r,C){return r[5]?We:r[4]?Ue:Ke}let X=re(t),P=X(t),E=t[3]&&be(t);function ue(r,C){return r[5]?Xe:r[0].length>0?Qe:Je}let Y=ue(t),I=Y(t);return{c(){e=d("div"),l=d("aside"),n=d("div"),n.innerHTML='⚒ Верстак',s=$(),i=d("nav"),o=d("div"),p=d("div"),p.textContent="Разделы",m=$();for(let r=0;rПоиск...',ce=$(),E&&E.c(),x=$(),K=d("div"),I.c(),a(n,"class","sidebar-top svelte-14ysusk"),a(p,"class","nav-label svelte-14ysusk"),a(o,"class","nav-group svelte-14ysusk"),a(g,"class","nav-label svelte-14ysusk"),a(_,"class","nav-group svelte-14ysusk"),a(i,"class","sidebar-nav svelte-14ysusk"),a(O,"class","version svelte-14ysusk"),a(T,"class","sidebar-bottom svelte-14ysusk"),a(l,"class","sidebar svelte-14ysusk"),a(G,"class","header-left svelte-14ysusk"),a(Q,"class","header-right svelte-14ysusk"),a(V,"class","header svelte-14ysusk"),a(K,"class","content svelte-14ysusk"),a(j,"class","main svelte-14ysusk"),a(e,"class","app svelte-14ysusk")},m(r,C){N(r,e,C),c(e,l),c(l,n),c(l,s),c(l,i),c(i,o),c(o,p),c(o,m);for(let f=0;f0?A||(A=ge(),A.c(),A.m(_,null)):A&&(A.d(1),A=null),C&4&&S(M,r[2]),X===(X=re(r))&&P?P.p(r,C):(P.d(1),P=X(r),P&&(P.c(),P.m(G,null))),r[3]?E?E.p(r,C):(E=be(r),E.c(),E.m(j,x)):E&&(E.d(1),E=null),Y===(Y=ue(r))&&I?I.p(r,C):(I.d(1),I=Y(r),I&&(I.c(),I.m(K,null)))},i:B,o:B,d(r){r&&L(e),le(y,r),le(w,r),A&&A.d(),P.d(),E&&E.d(),I.d()}}}function Ze(t,e,l){let n=[],s=[],i="",o="",p="",m=null;Ie(async()=>{try{l(2,i="verstak-gui"),window.go&&window.go.main&&window.go.main.App&&(l(2,i=await window.go.main.App.VerstakVersion()),l(0,n=await window.go.main.App.ListSections()),l(1,s=await window.go.main.App.ListRootNodes()))}catch(h){l(3,o=String(h))}});function u(h){l(4,p=h)}function _(h){l(5,m=h)}return[n,s,i,o,p,m,u,_,h=>u(h.id),h=>_(h)]}class xe extends De{constructor(e){super(),ze(this,e,Ze,Ye,Oe,{})}}new xe({target:document.getElementById("app")});
diff --git a/cmd/verstak-gui/frontend-dist/assets/index-ClxkTvdE.css b/cmd/verstak-gui/frontend-dist/assets/index-ClxkTvdE.css
deleted file mode 100644
index bda640a..0000000
--- a/cmd/verstak-gui/frontend-dist/assets/index-ClxkTvdE.css
+++ /dev/null
@@ -1 +0,0 @@
-.svelte-14ysusk.svelte-14ysusk,.svelte-14ysusk.svelte-14ysusk:before,.svelte-14ysusk.svelte-14ysusk:after{box-sizing:border-box;margin:0;padding:0}.app.svelte-14ysusk.svelte-14ysusk{display:flex;width:100vw;height:100vh;overflow:hidden;background:#13131f;color:#e4e4ef;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:14px}.sidebar.svelte-14ysusk.svelte-14ysusk{width:260px;min-width:200px;height:100vh;display:flex;flex-direction:column;background:#1a1a28;border-right:1px solid #2a2a3c;flex-shrink:0;overflow:hidden}.sidebar-top.svelte-14ysusk.svelte-14ysusk{padding:16px 20px;display:flex;align-items:center;gap:10px;border-bottom:1px solid #2a2a3c;flex-shrink:0}.logo.svelte-14ysusk.svelte-14ysusk{font-size:20px;line-height:1}.app-name.svelte-14ysusk.svelte-14ysusk{font-size:16px;font-weight:600;color:#e4e4ef}.sidebar-nav.svelte-14ysusk.svelte-14ysusk{flex:1;overflow-y:auto;padding:12px 0}.nav-group.svelte-14ysusk.svelte-14ysusk{margin-bottom:16px}.nav-label.svelte-14ysusk.svelte-14ysusk{font-size:10px;text-transform:uppercase;letter-spacing:.5px;color:#666;padding:4px 20px;margin-bottom:4px}.nav-item.svelte-14ysusk.svelte-14ysusk{display:block;width:100%;padding:8px 20px;border:none;background:none;color:#ccc;font-size:13px;text-align:left;cursor:pointer;border-radius:0;font-family:inherit}.nav-item.svelte-14ysusk.svelte-14ysusk:hover{background:#223}.nav-item.selected.svelte-14ysusk.svelte-14ysusk{background:#2a2a4a;color:#fff;font-weight:500}.nav-empty.svelte-14ysusk.svelte-14ysusk{padding:8px 20px;color:#555;font-size:12px}.sidebar-bottom.svelte-14ysusk.svelte-14ysusk{padding:12px 20px;border-top:1px solid #2a2a3c;flex-shrink:0}.version.svelte-14ysusk.svelte-14ysusk{font-size:11px;color:#555}.main.svelte-14ysusk.svelte-14ysusk{flex:1;display:flex;flex-direction:column;height:100vh;min-width:0;overflow:hidden;background:#13131f}.header.svelte-14ysusk.svelte-14ysusk{padding:12px 24px;border-bottom:1px solid #2a2a3c;display:flex;align-items:center;justify-content:space-between;flex-shrink:0;min-height:48px}.crumb.svelte-14ysusk.svelte-14ysusk{font-size:14px;font-weight:500;color:#e4e4ef}.crumb.placeholder.svelte-14ysusk.svelte-14ysusk{color:#666}.search-hint.svelte-14ysusk.svelte-14ysusk{padding:6px 12px;background:#1e1e2e;border:1px solid #2a2a3c;border-radius:4px;color:#666;font-size:12px;cursor:text}.error-banner.svelte-14ysusk.svelte-14ysusk{background:#3a2222;color:#f88;padding:8px 24px;font-size:12px;border-bottom:1px solid #4a2222;flex-shrink:0}.content.svelte-14ysusk.svelte-14ysusk{flex:1;overflow-y:auto;padding:24px}.welcome.svelte-14ysusk h2.svelte-14ysusk{font-size:28px;font-weight:300;margin-bottom:12px;color:#8888a4}.welcome.svelte-14ysusk p.svelte-14ysusk{color:#666;font-size:13px;margin-bottom:4px}.error-text.svelte-14ysusk.svelte-14ysusk{color:#f88;margin-top:12px}.loading.svelte-14ysusk.svelte-14ysusk{color:#666}.node-view.svelte-14ysusk h2.svelte-14ysusk{font-size:24px;margin-bottom:16px}.node-meta.svelte-14ysusk.svelte-14ysusk{display:flex;gap:16px;color:#666;font-size:12px}
diff --git a/cmd/verstak-gui/frontend-dist/assets/main-BqdVWy5o.js b/cmd/verstak-gui/frontend-dist/assets/main-BqdVWy5o.js
new file mode 100644
index 0000000..41a9e02
--- /dev/null
+++ b/cmd/verstak-gui/frontend-dist/assets/main-BqdVWy5o.js
@@ -0,0 +1,3 @@
+var pt=Object.defineProperty;var ht=(l,e,t)=>e in l?pt(l,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):l[e]=t;var ae=(l,e,t)=>ht(l,typeof e!="symbol"?e+"":e,t);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))n(s);new MutationObserver(s=>{for(const c of s)if(c.type==="childList")for(const i of c.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&n(i)}).observe(document,{childList:!0,subtree:!0});function t(s){const c={};return s.integrity&&(c.integrity=s.integrity),s.referrerPolicy&&(c.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?c.credentials="include":s.crossOrigin==="anonymous"?c.credentials="omit":c.credentials="same-origin",c}function n(s){if(s.ep)return;s.ep=!0;const c=t(s);fetch(s.href,c)}})();function Z(){}function Ye(l){return l()}function pe(){return Object.create(null)}function le(l){l.forEach(Ye)}function Ze(l){return typeof l=="function"}function vt(l,e){return l!=l?e==e:l!==e||l&&typeof l=="object"||typeof l=="function"}function bt(l){return Object.keys(l).length===0}function gt(l){return l??""}function f(l,e){l.appendChild(e)}function y(l,e,t){l.insertBefore(e,t||null)}function q(l){l.parentNode&&l.parentNode.removeChild(l)}function te(l,e){for(let t=0;tl.removeEventListener(e,t,n)}function kt(l){return function(e){e.target===this&&l.call(this,e)}}function a(l,e,t){t==null?l.removeAttribute(e):l.getAttribute(e)!==t&&l.setAttribute(e,t)}function $e(l){return l===""?null:+l}function qt(l){return Array.from(l.childNodes)}function D(l,e){e=""+e,l.data!==e&&(l.data=e)}function x(l,e){l.value=e??""}function he(l,e,t){for(let n=0;nl.indexOf(n)===-1?e.push(n):t.push(n)),t.forEach(n=>n()),oe=e}const Et=new Set;function Ot(l,e){l&&l.i&&(Et.delete(l),l.i(e))}function R(l){return(l==null?void 0:l.length)!==void 0?l:Array.from(l)}function Tt(l,e,t){const{fragment:n,after_update:s}=l.$$;n&&n.m(e,t),ue(()=>{const c=l.$$.on_mount.map(Ye).filter(Ze);l.$$.on_destroy?l.$$.on_destroy.push(...c):le(c),l.$$.on_mount=[]}),s.forEach(ue)}function Mt(l,e){const t=l.$$;t.fragment!==null&&(Lt(t.after_update),le(t.on_destroy),t.fragment&&t.fragment.d(e),t.on_destroy=t.fragment=null,t.ctx=[])}function Dt(l,e){l.$$.dirty[0]===-1&&(ce.push(l),St(),l.$$.dirty.fill(0)),l.$$.dirty[e/31|0]|=1<{const w=h.length?h[0]:p;return r.ctx&&s(r.ctx[d],r.ctx[d]=w)&&(!r.skip_bound&&r.bound[d]&&r.bound[d](w),m&&Dt(l,d)),p}):[],r.update(),m=!0,le(r.before_update),r.fragment=n?n(r.ctx):!1,e.target){if(e.hydrate){const d=qt(e.target);r.fragment&&r.fragment.l(d),d.forEach(q)}else r.fragment&&r.fragment.c();e.intro&&Ot(l.$$.fragment),Tt(l,e.target,e.anchor),xe()}fe(o)}class Pt{constructor(){ae(this,"$$");ae(this,"$$set")}$destroy(){Mt(this,1),this.$destroy=Z}$on(e,t){if(!Ze(t))return Z;const n=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return n.push(t),()=>{const s=n.indexOf(t);s!==-1&&n.splice(s,1)}}$set(e){this.$$set&&!bt(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}}const jt="4";typeof window<"u"&&(window.__svelte||(window.__svelte={v:new Set})).v.add(jt);function ge(l,e,t){const n=l.slice();return n[53]=e[t],n}function ke(l,e,t){const n=l.slice();return n[56]=e[t],n}function qe(l,e,t){const n=l.slice();return n[64]=e[t],n}function ye(l,e,t){const n=l.slice();return n[59]=e[t],n}function we(l,e,t){const n=l.slice();return n[56]=e[t],n}function Ce(l,e,t){const n=l.slice();return n[59]=e[t],n}function Ne(l,e,t){const n=l.slice();return n[69]=e[t],n}function Se(l,e,t){const n=l.slice();return n[53]=e[t],n}function Ae(l,e,t){const n=l.slice();return n[74]=e[t],n}function Le(l,e,t){const n=l.slice();return n[77]=e[t],n}function Ee(l){let e,t=l[77].label+"",n,s,c,i,u;function o(){return l[34](l[77])}return{c(){e=_("button"),n=S(t),s=k(),a(e,"class",c="nav-item "+(l[4]===l[77].id?"selected":"")+" svelte-1n16qmf")},m(r,m){y(r,e,m),f(e,n),f(e,s),i||(u=T(e,"click",o),i=!0)},p(r,m){l=r,m[0]&1&&t!==(t=l[77].label+"")&&D(n,t),m[0]&17&&c!==(c="nav-item "+(l[4]===l[77].id?"selected":"")+" svelte-1n16qmf")&&a(e,"class",c)},d(r){r&&q(e),i=!1,u()}}}function Oe(l){let e,t,n,s,c,i=l[1].length>0&&Te(l),u=R(l[1]),o=[];for(let m=0;m0?i?i.p(m,d):(i=Te(m),i.c(),i.m(t,null)):i&&(i.d(1),i=null),d[0]&2097186){u=R(m[1]);let p;for(p=0;p0)return zt;if(u[3])return Ut}let c=s(l),i=c&&c(l);return{c(){e=_("div"),t=_("h2"),t.textContent="Верстак",n=k(),i&&i.c(),a(t,"class","svelte-1n16qmf"),a(e,"class","welcome svelte-1n16qmf")},m(u,o){y(u,e,o),f(e,t),f(e,n),i&&i.m(e,null)},p(u,o){c===(c=s(u))&&i?i.p(u,o):(i&&i.d(1),i=c&&c(u),i&&(i.c(),i.m(e,null)))},d(u){u&&q(e),i&&i.d()}}}function Ft(l){let e,t,n,s=R(l[19]),c=[];for(let r=0;rАктивность появится позже
',a(e,"class","empty-state svelte-1n16qmf")},m(t,n){y(t,e,n)},p:Z,d(t){t&&q(e)}}}function Jt(l){let e,t,n,s,c,i,u,o,r,m,d,p;function h(v,A){return v[10].length===0?xt:$t}let w=h(l),g=w(l);return{c(){e=_("div"),t=_("div"),n=_("input"),s=k(),c=_("input"),i=k(),u=_("button"),o=S("Записать"),m=k(),g.c(),a(n,"type","text"),a(n,"placeholder","Что сделано"),a(n,"class","svelte-1n16qmf"),a(c,"type","number"),a(c,"placeholder","Мин"),a(c,"min","1"),a(c,"class","svelte-1n16qmf"),a(u,"class","btn btn-primary svelte-1n16qmf"),u.disabled=r=!l[12].trim()||!l[11],a(t,"class","worklog-form svelte-1n16qmf"),a(e,"class","worklog-tab svelte-1n16qmf")},m(v,A){y(v,e,A),f(e,t),f(t,n),x(n,l[12]),f(t,s),f(t,c),x(c,l[11]),f(t,i),f(t,u),f(u,o),f(e,m),g.m(e,null),d||(p=[T(n,"input",l[46]),T(c,"input",l[47]),T(u,"click",l[32])],d=!0)},p(v,A){A[0]&4096&&n.value!==v[12]&&x(n,v[12]),A[0]&2048&&$e(c.value)!==v[11]&&x(c,v[11]),A[0]&6144&&r!==(r=!v[12].trim()||!v[11])&&(u.disabled=r),w===(w=h(v))&&g?g.p(v,A):(g.d(1),g=w(v),g&&(g.c(),g.m(e,null)))},d(v){v&&q(e),g.d(),d=!1,le(p)}}}function Qt(l){let e;function t(c,i){return c[9].length===0?tl:el}let n=t(l),s=n(l);return{c(){s.c(),e=me()},m(c,i){s.m(c,i),y(c,e,i)},p(c,i){n===(n=t(c))&&s?s.p(c,i):(s.d(1),s=n(c),s&&(s.c(),s.m(e.parentNode,e)))},d(c){c&&q(e),s.d(c)}}}function Xt(l){let e;return{c(){e=_("div"),e.innerHTML='Нет файлов
Добавьте документы, скриншоты или папку с материалами.
Полноценная работа с файлами — следующий этап.
',a(e,"class","empty-state svelte-1n16qmf")},m(t,n){y(t,e,n)},p:Z,d(t){t&&q(e)}}}function Yt(l){let e,t,n,s,c,i,u,o=l[16]&&Be(l);function r(p,h){return p[7].length===0&&!p[16]?nl:ll}let m=r(l),d=m(l);return{c(){e=_("div"),t=_("div"),n=_("button"),n.textContent="+ Добавить заметку",s=k(),o&&o.c(),c=k(),d.c(),a(n,"class","btn btn-primary svelte-1n16qmf"),a(t,"class","tab-toolbar svelte-1n16qmf"),a(e,"class","notes-tab svelte-1n16qmf")},m(p,h){y(p,e,h),f(e,t),f(t,n),f(e,s),o&&o.m(e,null),f(e,c),d.m(e,null),i||(u=T(n,"click",l[25]),i=!0)},p(p,h){p[16]?o?o.p(p,h):(o=Be(p),o.c(),o.m(e,c)):o&&(o.d(1),o=null),m===(m=r(p))&&d?d.p(p,h):(d.d(1),d=m(p),d&&(d.c(),d.m(e,null)))},d(p){p&&q(e),o&&o.d(),d.d(),i=!1,u()}}}function Zt(l){let e,t,n=l[5].title+"",s,c,i,u,o,r,m=l[5].type+"",d,p,h,w,g,v=(l[5].section||"—")+"",A,I,B,U,M,E=ie(l[5].createdAt)+"",N,O,L,G,J,P,ne,Y,Q,j,W,C,F,H,V=l[7].length>0&&Fe(l),z=l[10].length>0&&Ue(l);return{c(){e=_("div"),t=_("h2"),s=S(n),c=k(),i=_("div"),u=_("div"),o=_("span"),o.textContent="Тип",r=_("span"),d=S(m),p=k(),h=_("div"),w=_("span"),w.textContent="Раздел",g=_("span"),A=S(v),I=k(),B=_("div"),U=_("span"),U.textContent="Создано",M=_("span"),N=S(E),O=k(),L=_("div"),G=_("button"),G.textContent="✏️ Новая заметка",J=k(),P=_("button"),P.textContent="📎 Добавить файл",ne=k(),Y=_("button"),Y.textContent="⚡ Добавить действие",Q=k(),j=_("button"),j.textContent="🕐 Записать время",W=k(),V&&V.c(),C=k(),z&&z.c(),a(t,"class","svelte-1n16qmf"),a(o,"class","meta-label svelte-1n16qmf"),a(r,"class","svelte-1n16qmf"),a(u,"class","meta-item svelte-1n16qmf"),a(w,"class","meta-label svelte-1n16qmf"),a(g,"class","svelte-1n16qmf"),a(h,"class","meta-item svelte-1n16qmf"),a(U,"class","meta-label svelte-1n16qmf"),a(M,"class","svelte-1n16qmf"),a(B,"class","meta-item svelte-1n16qmf"),a(i,"class","meta-grid svelte-1n16qmf"),a(G,"class","qa-btn svelte-1n16qmf"),a(P,"class","qa-btn svelte-1n16qmf"),P.disabled=!0,a(P,"title","Следующий этап"),a(Y,"class","qa-btn svelte-1n16qmf"),Y.disabled=!0,a(Y,"title","Следующий этап"),a(j,"class","qa-btn svelte-1n16qmf"),a(L,"class","quick-actions svelte-1n16qmf"),a(e,"class","overview svelte-1n16qmf")},m(K,ee){y(K,e,ee),f(e,t),f(t,s),f(e,c),f(e,i),f(i,u),f(u,o),f(u,r),f(r,d),f(i,p),f(i,h),f(h,w),f(h,g),f(g,A),f(i,I),f(i,B),f(B,U),f(B,M),f(M,N),f(e,O),f(e,L),f(L,G),f(L,J),f(L,P),f(L,ne),f(L,Y),f(L,Q),f(L,j),f(e,W),V&&V.m(e,null),f(e,C),z&&z.m(e,null),F||(H=[T(G,"click",l[39]),T(j,"click",l[40])],F=!0)},p(K,ee){ee[0]&32&&n!==(n=K[5].title+"")&&D(s,n),ee[0]&32&&m!==(m=K[5].type+"")&&D(d,m),ee[0]&32&&v!==(v=(K[5].section||"—")+"")&&D(A,v),ee[0]&32&&E!==(E=ie(K[5].createdAt)+"")&&D(N,E),K[7].length>0?V?V.p(K,ee):(V=Fe(K),V.c(),V.m(e,C)):V&&(V.d(1),V=null),K[10].length>0?z?z.p(K,ee):(z=Ue(K),z.c(),z.m(e,null)):z&&(z.d(1),z=null)},d(K){K&&q(e),V&&V.d(),z&&z.d(),F=!1,le(H)}}}function $t(l){let e,t=R(l[10]),n=[];for(let s=0;sЗаписей работы пока нет',a(e,"class","empty-state svelte-1n16qmf")},m(t,n){y(t,e,n)},p:Z,d(t){t&&q(e)}}}function He(l){let e,t,n=l[56].summary+"",s,c,i,u=l[56].minutes+"",o,r,m=ie(l[56].createdAt)+"",d,p;return{c(){e=_("div"),t=_("div"),s=S(n),c=k(),i=_("div"),o=S(u),r=S(" мин · "),d=S(m),p=k(),a(t,"class","svelte-1n16qmf"),a(i,"class","wl-meta svelte-1n16qmf"),a(e,"class","worklog-entry svelte-1n16qmf")},m(h,w){y(h,e,w),f(e,t),f(t,s),f(e,c),f(e,i),f(i,o),f(i,r),f(i,d),f(e,p)},p(h,w){w[0]&1024&&n!==(n=h[56].summary+"")&&D(s,n),w[0]&1024&&u!==(u=h[56].minutes+"")&&D(o,u),w[0]&1024&&m!==(m=ie(h[56].createdAt)+"")&&D(d,m)},d(h){h&&q(e)}}}function el(l){let e,t=R(l[9]),n=[];for(let s=0;sДействий пока нет',a(e,"class","empty-state svelte-1n16qmf")},m(t,n){y(t,e,n)},p:Z,d(t){t&&q(e)}}}function We(l){let e,t,n=l[64].title+"",s,c,i=l[64].type+"",u,o,r,m,d,p;function h(){return l[45](l[64])}return{c(){e=_("div"),t=_("span"),s=S(n),c=_("span"),u=S(i),o=k(),r=_("button"),r.textContent="Запустить",m=k(),a(t,"class","svelte-1n16qmf"),a(c,"class","action-type svelte-1n16qmf"),a(r,"class","btn btn-sm svelte-1n16qmf"),a(e,"class","action-card svelte-1n16qmf")},m(w,g){y(w,e,g),f(e,t),f(t,s),f(e,c),f(c,u),f(e,o),f(e,r),f(e,m),d||(p=T(r,"click",h),d=!0)},p(w,g){l=w,g[0]&512&&n!==(n=l[64].title+"")&&D(s,n),g[0]&512&&i!==(i=l[64].type+"")&&D(u,i)},d(w){w&&q(e),d=!1,p()}}}function Be(l){let e,t,n,s,c,i,u,o,r;return{c(){e=_("div"),t=_("input"),n=k(),s=_("div"),c=_("button"),c.textContent="Создать",i=k(),u=_("button"),u.textContent="Отмена",a(t,"type","text"),a(t,"placeholder","Название заметки"),a(t,"class","svelte-1n16qmf"),a(c,"class","btn btn-primary svelte-1n16qmf"),a(u,"class","btn svelte-1n16qmf"),a(s,"class","form-actions svelte-1n16qmf"),a(e,"class","create-form svelte-1n16qmf")},m(m,d){y(m,e,d),f(e,t),x(t,l[17]),f(e,n),f(e,s),f(s,c),f(s,i),f(s,u),o||(r=[T(t,"input",l[42]),T(t,"keydown",l[43]),T(c,"click",l[27]),T(u,"click",l[26])],o=!0)},p(m,d){d[0]&131072&&t.value!==m[17]&&x(t,m[17])},d(m){m&&q(e),o=!1,le(r)}}}function ll(l){let e,t=R(l[7]),n=[];for(let s=0;sНет заметокСоздайте первую заметку для этого дела.
',a(e,"class","empty-state svelte-1n16qmf")},m(t,n){y(t,e,n)},p:Z,d(t){t&&q(e)}}}function Re(l){let e,t,n=l[59].title+"",s,c,i,u=ie(l[59].createdAt)+"",o,r,m,d;function p(){return l[44](l[59])}return{c(){e=_("div"),t=_("div"),s=S(n),c=k(),i=_("div"),o=S(u),r=k(),a(t,"class","note-card-title svelte-1n16qmf"),a(i,"class","note-card-date svelte-1n16qmf"),a(e,"class","note-card svelte-1n16qmf")},m(h,w){y(h,e,w),f(e,t),f(t,s),f(e,c),f(e,i),f(i,o),f(e,r),m||(d=T(e,"click",p),m=!0)},p(h,w){l=h,w[0]&128&&n!==(n=l[59].title+"")&&D(s,n),w[0]&128&&u!==(u=ie(l[59].createdAt)+"")&&D(o,u)},d(h){h&&q(e),m=!1,d()}}}function Fe(l){let e,t,n,s=R(l[7].slice(0,5)),c=[];for(let i=0;il[50].call(h)),a(m,"class","form-group svelte-1n16qmf"),a(v,"class","btn btn-primary svelte-1n16qmf"),a(I,"class","btn svelte-1n16qmf"),a(g,"class","modal-actions svelte-1n16qmf"),a(t,"class","modal svelte-1n16qmf"),a(e,"class","modal-overlay svelte-1n16qmf")},m(N,O){y(N,e,O),f(e,t),f(t,n),f(t,s),f(t,c),f(c,i),f(c,u),f(c,o),x(o,l[14]),f(t,r),f(t,m),f(m,d),f(m,p),f(m,h);for(let L=0;L⚒ Верстак',s=k(),c=_("nav"),i=_("div"),u=_("div"),u.textContent="Разделы",o=k();for(let C=0;Cl.id!=="today"&&l.id!=="inbox";function sl(l,e,t){let n=[],s=[],c="",i="",u="",o=null,r="overview",m=[],d=null,p=[],h=[],w=[],g="",v="",A=!1,I="",B="clients",U=!1,M="",E=!0;const N=[{id:"overview",label:"Обзор"},{id:"notes",label:"Заметки"},{id:"files",label:"Файлы"},{id:"actions",label:"Действия"},{id:"worklog",label:"Журнал"},{id:"activity",label:"Активность"}];Ct(async()=>{try{t(2,c=await $("VerstakVersion")||"verstak-gui/v2"),t(0,n=await $("ListSections")||[])}catch(b){t(3,i=String(b)),t(0,n=[{id:"today",label:"Сегодня"},{id:"inbox",label:"Неразобранное"},{id:"clients",label:"Клиенты"},{id:"projects",label:"Проекты"},{id:"recipes",label:"Рецепты"},{id:"documents",label:"Документы"},{id:"archive",label:"Архив"}])}t(18,E=!1)});async function O(b){t(4,u=b),t(5,o=null),t(6,r="overview"),t(7,m=[]),p=[],t(9,h=[]),t(10,w=[]),t(13,A=!1),t(3,i="");try{t(1,s=await $("ListNodesBySection",b)||[])}catch(X){t(3,i=String(X)),t(1,s=[])}}async function L(b){t(5,o=b),t(6,r="overview"),t(7,m=[]),p=[],t(9,h=[]),t(10,w=[]),t(8,d=null),t(13,A=!1),t(16,U=!1),t(3,i=""),await G(b.id)}async function G(b){try{t(7,m=await $("ListNotes",b)||[])}catch{}try{p=await $("ListFiles",b)||[]}catch{}try{t(9,h=await $("ListActions",b)||[])}catch{}try{t(10,w=await $("ListWorklog",b)||[])}catch{}}function J(){t(13,A=!0),t(14,I=""),t(15,B=u||"clients")}function P(){t(13,A=!1),t(14,I="")}async function ne(){if(I.trim())try{const b=await $("CreateNode","","case",I.trim(),B);t(13,A=!1),t(14,I=""),await O(B)}catch(b){t(3,i=String(b))}}function Y(){t(16,U=!0),t(17,M="")}function Q(){t(16,U=!1),t(17,M="")}async function j(){if(!(!M.trim()||!o))try{const b=await $("CreateNote",o.id,M.trim());t(7,m=[...m,b&&b.id?b:{id:Date.now().toString(),title:M.trim(),createdAt:new Date().toISOString()}]),t(16,U=!1),t(17,M="")}catch{const X={id:Date.now().toString(),title:M.trim(),createdAt:new Date().toISOString()};t(7,m=[...m,X]),t(16,U=!1),t(17,M="")}}async function W(b){if(!(d&&d.dirty&&!confirm("Несохранённые изменения. Закрыть?")))try{const X=await $("ReadNote",b.id);t(8,d={id:b.id,title:b.title,content:X||"",dirty:!1})}catch{t(8,d={id:b.id,title:b.title,content:"# "+b.title+`
+
+`,dirty:!1})}}function C(){d&&d.dirty&&!confirm("Несохранённые изменения. Закрыть?")||t(8,d=null)}function F(b){d&&(t(8,d.content=b.target.value,d),t(8,d.dirty=!0,d))}async function H(){if(d)try{await $("SaveNote",d.id,d.content),t(8,d.dirty=!1,d)}catch{t(8,d.dirty=!1,d)}}async function V(){const b=parseInt(g,10);if(!(!v.trim()||isNaN(b)||b<=0||!o)){try{const X=await $("CreateWorklog",o.id,v.trim(),b);t(10,w=[...w,X&&X.id?X:{id:Date.now().toString(),nodeId:o.id,summary:v.trim(),minutes:b,createdAt:new Date().toISOString()}])}catch{t(10,w=[...w,{id:Date.now().toString(),nodeId:o.id,summary:v.trim(),minutes:b,createdAt:new Date().toISOString()}])}t(12,v=""),t(11,g="")}}function z(b){return r===b?"tab active":"tab"}const K=b=>O(b.id),ee=b=>L(b),et=()=>t(3,i="");function tt(){d.content=this.value,t(8,d)}const lt=b=>t(6,r=b.id),nt=()=>{t(6,r="notes"),Y()},it=()=>t(6,r="worklog"),st=b=>W(b);function ct(){M=this.value,t(17,M)}const ot=b=>b.key==="Enter"&&j(),ft=b=>W(b),rt=b=>$("RunAction",b.id);function ut(){v=this.value,t(12,v)}function at(){g=$e(this.value),t(11,g)}function dt(){I=this.value,t(14,I)}const _t=b=>b.key==="Enter"&&ne();function mt(){B=yt(this),t(15,B),t(0,n)}return[n,s,c,i,u,o,r,m,d,h,w,g,v,A,I,B,U,M,E,N,O,L,J,P,ne,Y,Q,j,W,C,F,H,V,z,K,ee,et,tt,lt,nt,it,st,ct,ot,ft,rt,ut,at,dt,_t,mt]}class cl extends Pt{constructor(e){super(),It(this,e,sl,il,vt,{},null,[-1,-1,-1])}}new cl({target:document.getElementById("app")});
diff --git a/cmd/verstak-gui/frontend-dist/assets/main-D8LYjC_e.css b/cmd/verstak-gui/frontend-dist/assets/main-D8LYjC_e.css
new file mode 100644
index 0000000..349b8d9
--- /dev/null
+++ b/cmd/verstak-gui/frontend-dist/assets/main-D8LYjC_e.css
@@ -0,0 +1 @@
+.svelte-1n16qmf.svelte-1n16qmf,.svelte-1n16qmf.svelte-1n16qmf:before,.svelte-1n16qmf.svelte-1n16qmf:after{box-sizing:border-box;margin:0;padding:0}.app.svelte-1n16qmf.svelte-1n16qmf{display:flex;width:100vw;height:100vh;overflow:hidden;background:#13131f;color:#e4e4ef;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:14px}.sidebar.svelte-1n16qmf.svelte-1n16qmf{width:260px;min-width:200px;height:100vh;display:flex;flex-direction:column;background:#1a1a28;border-right:1px solid #2a2a3c;flex-shrink:0;overflow:hidden}.sidebar-brand.svelte-1n16qmf.svelte-1n16qmf{padding:16px 20px;display:flex;align-items:center;gap:10px;border-bottom:1px solid #2a2a3c;flex-shrink:0}.logo.svelte-1n16qmf.svelte-1n16qmf{font-size:20px;line-height:1}.brand-name.svelte-1n16qmf.svelte-1n16qmf{font-size:16px;font-weight:600}.sidebar-nav.svelte-1n16qmf.svelte-1n16qmf{flex:1;overflow-y:auto;padding:12px 0}.nav-group.svelte-1n16qmf.svelte-1n16qmf{margin-bottom:16px}.nav-label.svelte-1n16qmf.svelte-1n16qmf{font-size:10px;text-transform:uppercase;letter-spacing:.5px;color:#666;padding:4px 20px;margin-bottom:4px}.nav-item.svelte-1n16qmf.svelte-1n16qmf{display:block;width:100%;padding:8px 20px;border:none;background:none;color:#ccc;font-size:13px;text-align:left;cursor:pointer;border-radius:0;font-family:inherit}.nav-item.svelte-1n16qmf.svelte-1n16qmf:hover{background:#223}.nav-item.selected.svelte-1n16qmf.svelte-1n16qmf{background:#2a2a4a;color:#fff;font-weight:500}.nav-empty.svelte-1n16qmf.svelte-1n16qmf{padding:8px 20px;color:#555;font-size:12px}.sidebar-footer.svelte-1n16qmf.svelte-1n16qmf{padding:12px 20px;border-top:1px solid #2a2a3c;flex-shrink:0}.version.svelte-1n16qmf.svelte-1n16qmf{font-size:11px;color:#555}.main.svelte-1n16qmf.svelte-1n16qmf{flex:1;display:flex;flex-direction:column;height:100vh;min-width:0;overflow:hidden;background:#13131f}.header.svelte-1n16qmf.svelte-1n16qmf{padding:12px 24px;border-bottom:1px solid #2a2a3c;display:flex;align-items:center;flex-shrink:0;min-height:48px}.crumb.svelte-1n16qmf.svelte-1n16qmf{font-size:14px;font-weight:500}.crumb.placeholder.svelte-1n16qmf.svelte-1n16qmf{color:#666}.crumb-type.svelte-1n16qmf.svelte-1n16qmf{font-size:11px;color:#555;background:#1e1e2e;padding:2px 8px;border-radius:10px;margin-left:8px}.error-banner.svelte-1n16qmf.svelte-1n16qmf{background:#3a2222;color:#f88;padding:8px 24px;font-size:12px;border-bottom:1px solid #4a2222;flex-shrink:0;cursor:pointer;display:flex;justify-content:space-between}.dismiss.svelte-1n16qmf.svelte-1n16qmf{opacity:.6}.tabs.svelte-1n16qmf.svelte-1n16qmf{display:flex;border-bottom:1px solid #2a2a3c;flex-shrink:0;padding:0 24px}.tab.svelte-1n16qmf.svelte-1n16qmf{padding:10px 16px;border:none;background:none;color:#888;font-size:13px;cursor:pointer;border-bottom:2px solid transparent;font-family:inherit}.tab.svelte-1n16qmf.svelte-1n16qmf:hover{color:#ccc}.tab.active.svelte-1n16qmf.svelte-1n16qmf{color:#e4e4ef;border-bottom-color:#6366f1}.tab-content.svelte-1n16qmf.svelte-1n16qmf{flex:1;overflow-y:auto}.note-editor.svelte-1n16qmf.svelte-1n16qmf{flex:1;display:flex;flex-direction:column;height:100%}.note-editor-header.svelte-1n16qmf.svelte-1n16qmf{padding:12px 24px;border-bottom:1px solid #2a2a3c;display:flex;align-items:center;gap:12px;flex-shrink:0}.note-title.svelte-1n16qmf.svelte-1n16qmf{font-size:16px;font-weight:500}.dirty-mark.svelte-1n16qmf.svelte-1n16qmf{color:#f59e0b;font-size:10px}.note-editor-actions.svelte-1n16qmf.svelte-1n16qmf{margin-left:auto;display:flex;gap:8px}.note-textarea.svelte-1n16qmf.svelte-1n16qmf{flex:1;width:100%;border:none;outline:none;background:#13131f;color:#e4e4ef;font-family:SF Mono,Fira Code,monospace;font-size:14px;line-height:1.6;padding:24px;resize:none}.overview.svelte-1n16qmf.svelte-1n16qmf{padding:24px}.overview.svelte-1n16qmf h2.svelte-1n16qmf{font-size:24px;margin-bottom:16px}.meta-grid.svelte-1n16qmf.svelte-1n16qmf{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px;margin-bottom:24px}.meta-item.svelte-1n16qmf.svelte-1n16qmf{background:#1a1a28;padding:12px 16px;border-radius:8px}.meta-label.svelte-1n16qmf.svelte-1n16qmf{display:block;font-size:11px;color:#666;margin-bottom:4px;text-transform:uppercase}.quick-actions.svelte-1n16qmf.svelte-1n16qmf{display:flex;gap:8px;margin-bottom:24px;flex-wrap:wrap}.qa-btn.svelte-1n16qmf.svelte-1n16qmf{padding:10px 16px;border:1px solid #2a2a3c;background:#1a1a28;color:#ccc;border-radius:8px;cursor:pointer;font-size:13px;font-family:inherit}.qa-btn.svelte-1n16qmf.svelte-1n16qmf:hover{background:#223}.qa-btn.svelte-1n16qmf.svelte-1n16qmf:disabled{opacity:.4;cursor:not-allowed}.recent-section.svelte-1n16qmf.svelte-1n16qmf{margin-bottom:24px}.recent-section.svelte-1n16qmf h3.svelte-1n16qmf{font-size:13px;color:#666;text-transform:uppercase;margin-bottom:8px}.recent-note.svelte-1n16qmf.svelte-1n16qmf{padding:8px 12px;border-radius:6px;cursor:pointer;display:flex;justify-content:space-between}.recent-note.svelte-1n16qmf.svelte-1n16qmf:hover{background:#1a1a28}.recent-date.svelte-1n16qmf.svelte-1n16qmf{font-size:11px;color:#555}.recent-entry.svelte-1n16qmf.svelte-1n16qmf{padding:6px 0;font-size:13px;color:#888;border-bottom:1px solid #1a1a28}.notes-tab.svelte-1n16qmf.svelte-1n16qmf{padding:24px}.tab-toolbar.svelte-1n16qmf.svelte-1n16qmf{margin-bottom:16px}.create-form.svelte-1n16qmf.svelte-1n16qmf{background:#1a1a28;padding:16px;border-radius:8px;margin-bottom:16px}.create-form.svelte-1n16qmf input.svelte-1n16qmf{width:100%;padding:8px 12px;border:1px solid #2a2a3c;background:#13131f;color:#e4e4ef;border-radius:4px;font-size:14px;font-family:inherit;margin-bottom:8px}.create-form.svelte-1n16qmf input.svelte-1n16qmf:focus{outline:none;border-color:#6366f1}.form-actions.svelte-1n16qmf.svelte-1n16qmf{display:flex;gap:8px}.notes-list.svelte-1n16qmf.svelte-1n16qmf{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px}.note-card.svelte-1n16qmf.svelte-1n16qmf{background:#1a1a28;border:1px solid #2a2a3c;border-radius:8px;padding:16px;cursor:pointer}.note-card.svelte-1n16qmf.svelte-1n16qmf:hover{border-color:#3a3a5c}.note-card-title.svelte-1n16qmf.svelte-1n16qmf{font-size:14px;font-weight:500;margin-bottom:4px}.note-card-date.svelte-1n16qmf.svelte-1n16qmf{font-size:11px;color:#555}.worklog-tab.svelte-1n16qmf.svelte-1n16qmf{padding:24px}.worklog-form.svelte-1n16qmf.svelte-1n16qmf{display:flex;gap:8px;margin-bottom:24px;align-items:center}.worklog-form.svelte-1n16qmf input.svelte-1n16qmf{padding:8px 12px;border:1px solid #2a2a3c;background:#13131f;color:#e4e4ef;border-radius:4px;font-size:14px;font-family:inherit}.worklog-form.svelte-1n16qmf input.svelte-1n16qmf:focus{outline:none;border-color:#6366f1}.worklog-form.svelte-1n16qmf input[type=text].svelte-1n16qmf{flex:1}.worklog-form.svelte-1n16qmf input[type=number].svelte-1n16qmf{width:70px}.worklog-entry.svelte-1n16qmf.svelte-1n16qmf{padding:12px 0;border-bottom:1px solid #1a1a28}.wl-meta.svelte-1n16qmf.svelte-1n16qmf{font-size:11px;color:#555;margin-top:2px}.action-card.svelte-1n16qmf.svelte-1n16qmf{background:#1a1a28;padding:12px 16px;border-radius:8px;display:flex;align-items:center;gap:12px;margin-bottom:8px}.action-type.svelte-1n16qmf.svelte-1n16qmf{font-size:11px;color:#888;background:#223;padding:2px 8px;border-radius:10px}.empty-state.svelte-1n16qmf.svelte-1n16qmf{padding:48px 24px;text-align:center}.empty-state.svelte-1n16qmf p.svelte-1n16qmf{color:#666;margin-bottom:8px}.hint.svelte-1n16qmf.svelte-1n16qmf{font-size:13px;color:#555}.empty-actions.svelte-1n16qmf.svelte-1n16qmf{display:flex;gap:8px;justify-content:center;margin:16px 0}.empty-note.svelte-1n16qmf.svelte-1n16qmf{font-size:12px;color:#444;margin-top:16px}.welcome.svelte-1n16qmf.svelte-1n16qmf{padding:48px 24px;text-align:center}.welcome.svelte-1n16qmf h2.svelte-1n16qmf{font-size:32px;font-weight:300;color:#8888a4;margin-bottom:16px}.welcome.svelte-1n16qmf p.svelte-1n16qmf{color:#666;font-size:14px}.error-text.svelte-1n16qmf.svelte-1n16qmf{color:#f88}.fab.svelte-1n16qmf.svelte-1n16qmf{position:fixed;bottom:24px;right:24px;width:56px;height:56px;border-radius:50%;background:#6366f1;color:#fff;font-size:28px;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 4px 12px #6366f166}.fab.svelte-1n16qmf.svelte-1n16qmf:hover{background:#4f46e5}.modal-overlay.svelte-1n16qmf.svelte-1n16qmf{position:fixed;top:0;right:0;bottom:0;left:0;background:#0009;display:flex;align-items:center;justify-content:center;z-index:100}.modal.svelte-1n16qmf.svelte-1n16qmf{background:#1a1a28;border:1px solid #2a2a3c;border-radius:12px;padding:24px;width:400px;max-width:90vw}.modal.svelte-1n16qmf h3.svelte-1n16qmf{font-size:18px;margin-bottom:16px}.form-group.svelte-1n16qmf.svelte-1n16qmf{margin-bottom:12px}.form-group.svelte-1n16qmf label.svelte-1n16qmf{display:block;font-size:12px;color:#666;margin-bottom:4px}.form-group.svelte-1n16qmf input.svelte-1n16qmf,.form-group.svelte-1n16qmf select.svelte-1n16qmf{width:100%;padding:8px 12px;border:1px solid #2a2a3c;background:#13131f;color:#e4e4ef;border-radius:4px;font-size:14px;font-family:inherit}.form-group.svelte-1n16qmf select.svelte-1n16qmf{-moz-appearance:none;appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23888' d='M2 4l4 4 4-4'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center;padding-right:32px}.form-group.svelte-1n16qmf input.svelte-1n16qmf:focus,.form-group.svelte-1n16qmf select.svelte-1n16qmf:focus{outline:none;border-color:#6366f1}.modal-actions.svelte-1n16qmf.svelte-1n16qmf{display:flex;gap:8px;justify-content:flex-end;margin-top:16px}.btn.svelte-1n16qmf.svelte-1n16qmf{padding:8px 16px;border:1px solid #2a2a3c;background:#1a1a28;color:#ccc;border-radius:6px;cursor:pointer;font-size:13px;font-family:inherit}.btn.svelte-1n16qmf.svelte-1n16qmf:hover{background:#223}.btn-primary.svelte-1n16qmf.svelte-1n16qmf{background:#6366f1;border-color:#6366f1;color:#fff}.btn-primary.svelte-1n16qmf.svelte-1n16qmf:hover{background:#4f46e5}.btn.svelte-1n16qmf.svelte-1n16qmf:disabled{opacity:.4;cursor:not-allowed}.btn-sm.svelte-1n16qmf.svelte-1n16qmf{padding:4px 10px;font-size:12px}
diff --git a/cmd/verstak-gui/frontend-dist/index.html b/cmd/verstak-gui/frontend-dist/index.html
index fe3a465..34871bb 100644
--- a/cmd/verstak-gui/frontend-dist/index.html
+++ b/cmd/verstak-gui/frontend-dist/index.html
@@ -16,8 +16,8 @@
background: #13131f;
}
-
-
+
+
diff --git a/cmd/verstak-gui/main.go b/cmd/verstak-gui/main.go
index c127650..a9207b9 100644
--- a/cmd/verstak-gui/main.go
+++ b/cmd/verstak-gui/main.go
@@ -49,7 +49,6 @@ func main() {
worklogSvc := worklog.NewService(db)
searchSvc := search.NewService(db)
plugins.NewManager(abs).Discover()
- _ = searchSvc
app := &App{
db: db,
@@ -58,6 +57,7 @@ func main() {
notes: noteSvc,
actions: actionSvc,
worklog: worklogSvc,
+ search: searchSvc,
vault: abs,
}
diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte
index 94283ae..9b70196 100644
--- a/frontend/src/App.svelte
+++ b/frontend/src/App.svelte
@@ -1,43 +1,214 @@