1import{r as m,j as e}from"./query-D-1Fd3VD.js";import{L as U}from"./react-vendor-BFQkvBUU.js";import{m as w,k as F,K as C,L as q,M as B,O,z as P,Q as L,R,E}from"./index-CiuSZZkR.js";import{M as I}from"./Modal-B8ciYfkt.js";import"./firebase-BcC49jKU.js";import"./analytics-CYLNOODP.js";const k=120;function A(t){const a=new Date(t);if(Number.isNaN(a.getTime()))return"";const s=x=>String(x).padStart(2,"0"),l=a.getUTCFullYear(),r=s(a.getUTCMonth()+1),n=s(a.getUTCDate()),d=s(a.getUTCHours()),u=s(a.getUTCMinutes());return`${l}-${r}-${n}T${d}:${u}`}const Y=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?$/;function M(t){if(!t||!Y.test(t))return null;const a=t.length===16?`${t}:00Z`:`${t}Z`,s=new Date(a);return Number.isNaN(s.getTime())?null:s.toISOString()}function T(t){const a={},s=t.label.trim();return s.length===0?a.label="Label is required.":s.length>k&&(a.label=`Label must be ${k} characters or fewer.`),t.timestamp_local?M(t.timestamp_local)===null&&(a.timestamp_utc="Timestamp must be a valid date."):a.timestamp_utc="Timestamp is required.",a}const v="__universal__";function D({mode:t,onSubmit:a,onCancel:s,submitting:l=!1}){const r=t.kind==="edit"?t.row:null,[n,d]=m.useState(r?.label??""),[u,x]=m.useState(r?A(r.timestamp_utc):""),[c,h]=m.useState(r?.asset&&w(r.asset)?r.asset:v),[y,f]=m.useState(r?r.enabled:!0),[b,p]=m.useState({}),[o,j]=m.useState(!1);m.useEffect(()=>{t.kind==="edit"?(d(t.row.label),x(A(t.row.timestamp_utc)),h(t.row.asset&&w(t.row.asset)?t.row.asset:v),f(t.row.enabled),p({}),j(!1)):(d(""),x(""),h(v),f(!0),p({}),j(!1))},[t]);function S(i){i.preventDefault();const _=T({label:n,timestamp_local:u});if(p(_),j(!0),Object.keys(_).length>0)return;const $=M(u);a({label:n.trim(),timestamp_utc:$,asset:c===v?null:c,enabled:y})}const N=t.kind==="edit",g=l?N?"Savingâ¦":"Creatingâ¦":N?"Save changes":"Create anchor";return e.jsxs("form",{onSubmit:S,noValidate:!0,"data-testid":"manual-anchor-form","data-mode":t.kind,className:"flex max-w-[560px] flex-col gap-3 rounded-lg border border-border-subtle bg-bg-surface p-4",children:[e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{htmlFor:"ma-label",className:"font-mono text-micro uppercase tracking-data text-text-muted",children:"Label"}),e.jsx("input",{id:"ma-label",type:"text",value:n,maxLength:k,onChange:i=>d(i.target.value),onBlur:()=>p(T({label:n,timestamp_local:u})),required:!0,"aria-invalid":o&&!!b.label,"aria-describedby":b.label?"ma-label-err":void 0,className:"rounded-md border border-border-subtle bg-bg-page px-3 py-2 font-body text-body text-text-primary focus:border-cyan-signal focus:outline-none"}),e.jsxs("p",{className:"m-0 font-mono text-micro tracking-data text-text-muted",children:[n.length,"/",k]}),o&&b.label&&e.jsx("p",{id:"ma-label-err",role:"alert",className:"m-0 font-body text-small text-violet-alert",children:b.label})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{htmlFor:"ma-timestamp",className:"font-mono text-micro uppercase tracking-data text-text-muted",children:"Timestamp (UTC)"}),e.jsx("input",{id:"ma-timestamp",type:"datetime-local",value:u,onChange:i=>x(i.target.value),onBlur:()=>p(T({label:n,timestamp_local:u})),required:!0,"aria-invalid":o&&!!b.timestamp_utc,"aria-describedby":b.timestamp_utc?"ma-timestamp-err":void 0,className:"rounded-md border border-border-subtle bg-bg-page px-3 py-2 font-body text-body text-text-primary focus:border-cyan-signal focus:outline-none"}),o&&b.timestamp_utc&&e.jsx("p",{id:"ma-timestamp-err",role:"alert",className:"m-0 font-body text-small text-violet-alert",children:b.timestamp_utc})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{htmlFor:"ma-asset",className:"font-mono text-micro uppercase tracking-data text-text-muted",children:"Scope"}),e.jsxs("select",{id:"ma-asset",value:c,onChange:i=>h(i.target.value),className:"rounded-md border border-border-subtle bg-bg-page px-3 py-2 font-body text-body text-text-primary focus:border-cyan-signal focus:outline-none",children:[e.jsx("option",{value:v,children:"Universal (all assets)"}),F.map(i=>e.jsxs("option",{value:i,children:[C[i].displayName," (",C[i].shortL
1abel,")"]},i))]})]}),e.jsxs("label",{htmlFor:"ma-enabled",className:"flex cursor-pointer items-center gap-2 font-body text-small text-text-primary",children:[e.jsx("input",{id:"ma-enabled",type:"checkbox",checked:y,onChange:i=>f(i.target.checked),className:"h-4 w-4 cursor-pointer accent-cyan-signal"}),"Enabled (forecast engine uses this anchor)"]}),e.jsxs("div",{className:"mt-1 flex items-center justify-end gap-3",children:[s&&e.jsx("button",{type:"button",onClick:s,disabled:l,className:"cursor-pointer rounded-md border border-border-subtle bg-transparent px-4 py-2 font-body text-small font-medium text-text-secondary hover:border-border-strong hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-50",children:"Cancel"}),e.jsx("button",{type:"submit",disabled:l,"data-testid":"manual-anchor-submit",className:"cursor-pointer rounded-md border border-cyan-soft bg-transparent px-4 py-2 font-body text-small font-semibold text-cyan-signal hover:border-cyan-signal disabled:cursor-not-allowed disabled:opacity-50",children:g})]})]})}function Q(t){const a=new Date(t);if(Number.isNaN(a.getTime()))return t;const s=a.getUTCFullYear(),l=String(a.getUTCMonth()+1).padStart(2,"0"),r=String(a.getUTCDate()).padStart(2,"0"),n=String(a.getUTCHours()).padStart(2,"0"),d=String(a.getUTCMinutes()).padStart(2,"0");return`${s}-${l}-${r} ${n}:${d} UTC`}function V(t){return t?w(t)?C[t].shortLabel:t:"Universal"}function H({row:t}){const[a,s]=m.useState(!1),[l,r]=m.useState(!1),n=q(),d=B();function u(){n.mutate({id:t.id,patch:{enabled:!t.enabled}})}function x(){d.mutate({id:t.id},{onSettled:()=>{r(!1)}})}return a?e.jsx("li",{"data-testid":`manual-anchor-row-${t.id}`,"data-row-mode":"edit",className:"list-none",children:e.jsx(D,{mode:{kind:"edit",row:t},submitting:n.isPending,onCancel:()=>s(!1),onSubmit:async c=>{await n.mutateAsync({id:t.id,patch:{label:c.label,timestamp_utc:c.timestamp_utc,asset:c.asset,enabled:c.enabled}}),s(!1)}})}):e.jsxs("li",{"data-testid":`manual-anchor-row-${t.id}`,"data-row-mode":"view","data-enabled":t.enabled,className:"list-none rounded-lg border border-border-subtle bg-bg-surface px-4 py-3",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("p",{className:"m-0 font-body text-body font-semibold text-text-primary",children:t.label}),!t.enabled&&e.jsx("span",{className:"rounded-pill border border-border-subtle px-2 py-0.5 font-mono text-micro font-semibold uppercase tracking-data text-text-muted",children:"disabled"})]}),e.jsxs("p",{className:"mt-1 mb-0 font-mono text-micro tracking-data text-text-secondary",children:[Q(t.timestamp_utc)," · scope:"," ",V(t.asset)]})]}),e.jsxs("div",{className:"flex shrink-0 items-center gap-2",children:[e.jsx("button",{type:"button",onClick:u,disabled:n.isPending,"data-testid":`manual-anchor-toggle-${t.id}`,"aria-label":t.enabled?"Disable":"Enable",className:"cursor-pointer rounded-md border border-border-subtle bg-transparent px-3 py-1 font-body text-small text-text-secondary hover:border-border-strong hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-50",children:t.enabled?"Disable":"Enable"}),e.jsx("button",{type:"button",onClick:()=>s(!0),"data-testid":`manual-anchor-edit-${t.id}`,className:"cursor-pointer rounded-md border border-border-subtle bg-transparent px-3 py-1 font-body text-small text-text-secondary hover:border-border-strong hover:text-text-primary",children:"Edit"}),e.jsx("button",{type:"button",onClick:()=>r(!0),"data-testid":`manual-anchor-delete-${t.id}`,"aria-label":"Delete",className:"cursor-pointer rounded-md border border-violet-soft bg-transparent px-3 py-1 font-body text-small text-violet-alert hover:border-violet-alert",children:"Delete"})]})]}),e.jsx(I,{open:l,onClose:()=>r(!1),variant:"danger",title:"Delete this manual anchor?",actions:e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",onClick:()=>r(!1),disabled:d.isPending,className:"cursor-pointer rounded-md border border-border-subtle bg-transparent px-4 py-2 font-body text-small font-medium text-text-secondary hover:border-border-strong hover:text-text-primary disabled:cursor-not-allowed disabled:opacity-50",children:"Cancel"}),e.jsx("button",{type:"button",onClick:x,disabled:d.isPending,"data-testid":`manual-anchor-confirm-delete-${t.id}`,className:"cursor-pointer rounded-md border border-violet-alert bg-transparent px-4 py-2 font-body text-small font-semibold text-violet-alert hover:bg-violet-soft/10 disabled:cursor-not-allowed disabled:opacity-50",children:d.isPending?"Deletingâ¦":"Delete"})]}),children:e.jsxs("p",{className:"m-0",children:[e.jsx("strong",{className:"text-text-primary",children:t.label})," will be removed from the engineâs anchor catalog. This is a soft-delete on the server; rows can be restored by an operator."]})})]})}function W(){const{asset:t}=O(),a=C[t],{showToast:s}=P(),[l,r]=m.useState(!0),[n,d]=m.useState(!1),[u,x]=m.useState(!1),c=L({asset:t,includeDisabled:n}),h=L({asset:null,includeDisabled:n}),y=R(),f=m.useMemo(()=>
1{const o=c.data??[],j=l?h.data??[]:[],S=new Set,N=[...o,...j].filter(g=>S.has(g.id)?!1:(S.add(g.id),!0));return N.sort((g,i)=>i.timestamp_utc.localeCompare(g.timestamp_utc)),N},[c.data,h.data,l]),b=c.isLoading||l&&h.isLoading,p=c.isError||l&&h.isError;return e.jsxs("article",{children:[e.jsxs("header",{className:"border-b border-border-subtle py-5",children:[e.jsx(U,{to:"/settings",className:"font-body text-small text-text-secondary no-underline hover:text-text-primary",children:"â Settings"}),e.jsx("h1",{className:"mt-2 mb-0 font-display text-title font-medium tracking-tight text-text-primary",children:"Manual anchors"}),e.jsxs("p",{className:"mt-2 mb-0 max-w-[64ch] font-body text-small leading-relaxed text-text-secondary",children:["User-defined anchor points the engine treats as inputs to the forecast. Scope to a specific asset or leave universal. Youâre currently viewing"," ",e.jsx("strong",{className:"text-text-primary",children:a.displayName}),l?" + universal":"","."]})]}),e.jsxs("section",{className:"mt-6 flex flex-col gap-3","aria-labelledby":"ma-filters",children:[e.jsx("h2",{id:"ma-filters",className:"m-0 font-mono text-micro uppercase tracking-data text-text-muted",children:"Filters"}),e.jsxs("div",{className:"flex flex-wrap gap-4",children:[e.jsxs("label",{htmlFor:"ma-show-universal",className:"flex cursor-pointer items-center gap-2 font-body text-small text-text-secondary",children:[e.jsx("input",{id:"ma-show-universal",type:"checkbox",checked:l,onChange:o=>r(o.target.checked),className:"h-4 w-4 cursor-pointer accent-cyan-signal"}),"Show universal anchors too"]}),e.jsxs("label",{htmlFor:"ma-include-disabled",className:"flex cursor-pointer items-center gap-2 font-body text-small text-text-secondary",children:[e.jsx("input",{id:"ma-include-disabled",type:"checkbox",checked:n,onChange:o=>d(o.target.checked),className:"h-4 w-4 cursor-pointer accent-cyan-signal"}),"Include disabled"]})]})]}),e.jsxs("section",{className:"mt-6","aria-labelledby":"ma-create",children:[e.jsxs("div",{className:"mb-3 flex items-center justify-between gap-3",children:[e.jsx("h2",{id:"ma-create",className:"m-0 font-display text-h1 font-medium tracking-tight text-text-primary",children:"New anchor"}),!u&&e.jsx("button",{type:"button",onClick:()=>x(!0),"data-testid":"manual-anchor-open-create",className:"cursor-pointer rounded-md border border-cyan-soft bg-transparent px-4 py-2 font-body text-small font-semibold text-cyan-signal hover:border-cyan-signal",children:"+ Add anchor"})]}),u&&e.jsx(D,{mode:{kind:"create"},submitting:y.isPending,onCancel:()=>x(!1),onSubmit:async o=>{try{await y.mutateAsync({label:o.label,timestamp_utc:o.timestamp_utc,asset:o.asset,enabled:o.enabled}),s({variant:"success",message:"Anchor created."}),x(!1)}catch{}}})]}),e.jsxs("section",{className:"mt-7","aria-labelledby":"ma-list","data-testid":"manual-anchors-list",children:[e.jsx("h2",{id:"ma-list",className:"m-0 mb-3 font-display text-h1 font-medium tracking-tight text-text-primary",children:"Anchors"}),b&&e.jsx("div",{role:"status",className:"rounded-md border border-border-subtle bg-bg-surface px-4 py-3 font-body text-small text-text-secondary",children:"Loading anchorsâ¦"}),p&&e.jsx(E,{variant:"error",title:"Couldn't load anchors",body:"The forecast engine isn't responding. Refresh the page to retry."}),!b&&!p&&f.length===0&&e.jsx(E,{variant:"quiet-day",title:"No manual anchors yet",body:`Add an anchor scoped to ${a.shortLabel} or universal â the engine will use it on the next forecast run.`}),!b&&!p&&f.length>0&&e.jsx("ul",{"data-testid":"manual-anchors-rows",className:"m-0 flex max-w-[680px] flex-col gap-2 p-0",children:f.map(o=>e.jsx(H,{row:o},o.id))})]})]})}export{W as default}; 2//# sourceMappingURL=ManualAnchors-qQEvlX4N.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.