PageSourceSearch

https://aktywa.netlify.app/assets/Admin-C0HlcIC5.js

js aktywa.netlify.app collected 2026-10-03 10:26:29 UTC 73,718 bytes, 16 lines download raw bytes

1import{e as se,s as xe,a as ve,j as e,ai as Se,r as L,h as K,X as pe,c as M,i as C}from"./index-CaWDYMXN.js";import{u as T}from"./useQuery-B5oAOMdn.js";import{u as R}from"./useMutation-P0ptm2N2.js";import{B as $}from"./button-CS4yFmc0.js";import{C as Le,a as Te}from"./card-BCAOyHS8.js";import{T as Ae,a as Ce,b as P,c as _}from"./tabs-BLM9f_Ck.js";import{T as F,a as q,b as v,c as w,d as B,e as g}from"./table-Dq1UP2aN.js";import{P as Pe}from"./PageHeader-B4EuBES5.js";import{u as _e}from"./useUrlTab-ztxOYc7-.js";import{i as he}from"./edgeInvokeError-CwXYQxsh.js";import{T as Ee}from"./textarea-C_c84L72.js";import{S as De,a as Ue,b as $e,c as Oe,d as Fe}from"./select-DFyrlrL3.js";import{L as qe,D as Be,u as Ie,p as Me,T as oe}from"./index-eN7rEBOq.js";import{U as Ke}from"./users-Cz3onSxy.js";import{A as le}from"./activity-Ctm5hB6y.js";import{B as ye}from"./bell-Hf1zem5X.js";import{C as Re}from"./cpu-DI32oxVu.js";import{L as W}from"./loader-circle-zaoxP4mL.js";import{I as ae}from"./info-DLue9B_S.js";import{R as We}from"./refresh-cw-C-qW632C.js";import{S as je}from"./shield-check-BT_Jtamg.js";import{T as J}from"./triangle-alert-BZ_SikID.js";import{C as He}from"./chevron-down-WDQNsyI6.js";import{C as Xe}from"./chevron-right-C7t6jCS5.js";import{C as ge}from"./check-DyfCj8G6.js";import{R as Ge}from"./rotate-ccw-IPfhfqUm.js";import"./index-Py-sD2PV.js";import"./index-syrsIAle.js";import"./index-AYbuW7hu.js";import"./chevron-up-5P5uyQFQ.js";import"./yahoo-DfEq4YZI.js";/**
2 * @license lucide-react v0.462.0 - ISC
3 *
4 * This source code is licensed under the ISC license.
5 * See the LICENSE file in the root directory of this source tree.
6 */const te=se("FileUp",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M12 12v6",key:"3ahymv"}],["path",{d:"m15 15-3-3-3 3",key:"15xj92"}]]);/**
7 * @license lucide-react v0.462.0 - ISC
8 *
9 * This source code is licensed under the ISC license.
10 * See the LICENSE file in the root directory of this source tree.
11 */const Qe=se("MessageSquareText",[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z",key:"1lielz"}],["path",{d:"M13 8H7",key:"14i4kc"}],["path",{d:"M17 12H7",key:"16if0g"}]]);/**
12 * @license lucide-react v0.462.0 - ISC
13 *
14 * This source code is licensed under the ISC license.
15 * See the LICENSE file in the root directory of this source tree.
16 */const Ze=se("Percent",[["line",{x1:"19",x2:"5",y1:"5",y2:"19",key:"1x9vlm"}],["circle",{cx:"6.5",cy:"6.5",r:"2.5",key:"4mh3h7"}],["circle",{cx:"17.5",cy:"17.5",r:"2.5",key:"1mdrzq"}]]),Ye=s=>!!s&&Date.now()-new Date(s).getTime()<24*60*60*1e3,Q=s=>s==null?null:new Date(Date.now()-s*6e4).toISOString();function Ve(s,a){const p=(a==null?void 0:a.errors)??[],u=z=>p.filter(H=>z(H)&&Ye(H.createdAt)).length,t=[],r=u(z=>z.kind==="quote_failed"),c=(s==null?void 0:s.stale)??0,o=(s==null?void 0:s.fresh)??0,y=(s==null?void 0:s.oldestMin)??null,j=y!=null?y/(24*60):0,n=new Date().getDay(),d=n===0||n===6?3.5:.9,m=s&&c>o?"down":s&&j>d?"warn":"ok";let x=s?`${o} świeżych / ${c} nieaktualnych`:"—";s&&y!=null&&y>=60&&(x+=j>=1?`, najstarszy ${Math.floor(j)} d`:`, najstarszy ${Math.round(y/60)} h`),r>0&&(x+=`, ${r} błędów pobrania (24h)`),t.push({name:"Notowania (ceny)",status:m,errors24h:r,lastOk:Q((s==null?void 0:s.newestMin)??null),detail:x});const i=u(z=>z.kind==="fx_failed"||/fx|currency/.test(z.source.toLowerCase())),h=(s==null?void 0:s.fxAgeMin)??null;t.push({name:"Kursy walut (FX)",status:i>0||h==null?"down":h>24*60?"warn":"ok",errors24h:i,lastOk:Q(h),detail:h==null?"brak danych FX":`wiek ${Math.round(h)} min`});const f=(s==null?void 0:s.newestMin)??null;t.push({name:"Cron notowań (refresh-quotes)",status:f==null||f>24*60?"down":f>120?"warn":"ok",errors24h:0,lastOk:Q(f),detail:f==null?"cache pusty — cron mógł nie wystartować":`ostatni wpis ${Math.round(f)} min temu`});const k=(a==null?void 0:a.health)??null,b=k?(Date.now()-new Date(k.createdAt).getTime())/6e4:null;t.push({name:"Strażnik danych (data-health)",status:k==null||b!=null&&b>48*60?"down":!k.ok||b!=null&&b>36*60?"warn":"ok",errors24h:0,lastOk:(k==null?void 0:k.createdAt)??null,detail
16:k==null?"nigdy nie zapisał przebiegu":k.ok?"ostatni przebieg OK":"ostatni przebieg z uwagami"});const S=u(z=>z.kind==="import_failed"||z.kind==="backfill_failed"||z.kind==="parse_failed");return t.push({name:"Import / backfill",status:S>0?"warn":"ok",errors24h:S,lastOk:null,detail:S>0?`${S} błędów w 24h`:"bez błędów (24h)"}),t.push({name:"Baza danych (Supabase)",status:s||a?"ok":"warn",errors24h:0,lastOk:s||a?new Date().toISOString():null,detail:s||a?"odpowiada":"brak odpowiedzi"}),t}function Je(s){return s.some(a=>a.status==="down")?"down":s.some(a=>a.status==="warn")?"warn":"ok"}async function N(s,a={}){const{data:p,error:u}=await xe.functions.invoke("admin-stats",{body:{action:s,...a}});if(u)throw new Error(await he(u,`admin-stats ${s} failed`));const t=p;if(t&&typeof t=="object"&&"error"in t&&t.error)throw new Error(String(t.error));return t}const es=()=>N("overview"),ss=()=>N("users"),as=()=>N("coverage"),ts=()=>N("prompts"),ns=(s,a)=>N("set-prompt",{key:s,text:a}),rs=()=>N("list-models"),is=(s,a)=>N("set-model",{key:s,model:a}),os=(s=30)=>N("ai-usage",{days:s}),ls=(s=90)=>N("logins",{days:s}),cs=(s=30)=>N("ai-usage-users",{days:s}),we=()=>N("health"),ds=()=>N("imports"),fe=()=>N("errors"),ms=()=>N("provider-usage"),us=()=>N("refresh-quotes"),xs=s=>N("set-tax-settings",s);async function ps(){const{data:s,error:a}=await xe.functions.invoke("data-health",{body:{}});if(a)throw new Error(await he(a,"data-health run failed"));return s}function U(s){const a=typeof s=="string"?Number(s):s;return typeof a=="number"&&Number.isFinite(a)?a:0}function hs(s,a,p=new Date){const u=new Date(p.getTime()-(a-1)*864e5).toISOString().slice(0,10),t=new Map,r=new Map;let c=null,o=null,y=0,j=0,n=0;for(const i of s){if(!i||typeof i.day!="string"||i.day<u)continue;const h=`${i.fn}\0${i.stage}`;let f=t.get(h);f||(f={fn:i.fn,stage:i.stage,models:[],modelSet:new Set,calls:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,costUsd:0,batchCalls:0,unpricedCalls:0,cacheShare:null},t.set(h,f));const k=U(i.calls),b=U(i.est_cost_usd);f.modelSet.add(i.model),f.calls+=k,f.inputTokens+=U(i.input_tokens),f.outputTokens+=U(i.output_tokens),f.cacheReadTokens+=U(i.cache_read_tokens),f.cacheWriteTokens+=U(i.cache_write_tokens),f.costUsd+=b,i.batch&&(f.batchCalls+=k),f.unpricedCalls+=U(i.unpriced_calls);const S=r.get(i.day)??{costUsd:0,calls:0};S.costUsd+=b,S.calls+=k,r.set(i.day,S),y+=b,j+=k,n+=U(i.unpriced_calls),(c===null||i.day<c)&&(c=i.day),(o===null||i.day>o)&&(o=i.day)}const l=[...t.values()].map(({modelSet:i,...h})=>{const f=h.inputTokens+h.cacheReadTokens+h.cacheWriteTokens;return{...h,models:[...i].sort(),costUsd:X(h.costUsd),cacheShare:f>0?h.cacheReadTokens/f:null}}).sort((i,h)=>h.costUsd-i.costUsd||h.calls-i.calls),d=[...r.entries()].map(([i,h])=>({day:i,costUsd:X(h.costUsd),calls:h.calls})).sort((i,h)=>i.day<h.day?1:i.day>h.day?-1:0),m=new Map;for(const i of l){const h=m.get(i.fn)??{costUsd:0,calls:0};h.costUsd+=i.costUsd,h.calls+=i.calls,m.set(i.fn,h)}const x=[...m.entries()].map(([i,h])=>({fn:i,costUsd:X(h.costUsd),calls:h.calls,share:y>0?h.costUsd/y:0})).sort((i,h)=>h.costUsd-i.costUsd||h.calls-i.calls);return{from:c,to:o,days:a,totalCostUsd:X(y),totalCalls:j,unpricedCalls:n,stages:l,perDay:d,functions:x}}function X(s){return Math.round(s*1e6)/1e6}function A(s){const a=s>0&&s<.01?3:2;return`${s.toLocaleString("pl-PL",{minimumFractionDigits:a,maximumFractionDigits:a})} $`}const ys={"kb-import":"baza wiedzy: import","kb-yt-watch":"baza wiedzy: automat YouTube (destylator, bramka)","kb-ingest":"baza wiedzy: indeksowanie","kb-search":"tutor Akademii","kb-quiz":"quizy Akademii","kb-generate-script":"generator skryptów","kb-generate-course":"generator kursów","kb-generate-analysis":"asystent analiz","kb-admin":"panel bazy wiedzy","kb-tts":"lektor (przygotowanie tekstu)","company-analysis":"analiza spółki (dossier)","soft-analysis":"skaner: analiza miękka (lekcja 5)","signal-interpret":"portfele modelowe: interpretacja przeceny","macro-comment":"makro: komentarz do barometru","geo-hotspots":"makro: punkty zapalne (geopolityka)","headlines-translate":"nagłówki: tłumaczenie na polski","company-report":"raport spółki","daily-brief":"brief poranny","yt-serwis":"serwis dnia (Rynkowy Ekspres)","ai-categorize":"prywatny portfel: kategorie","ai-merchant-info":"prywatny portfel: sprzedawcy","ai-restructure":"prywatny portfel: restrukturyzacja","prepare-import":"prywatny portfel: import wyciągu"};function be(s){return ys[s]??s}const js={"headlines-translate/tlumaczenie":"tłumaczenie nagłówków (Geopolityka, Polymarket, Rynki)","kb-import/import":"import kawałków transkryptu (lekcja)","kb-import/qa-split":"podział transkryptu na pary Q&A","kb-import/qa":"opis pary Q&A","kb-yt-watch/distill":"destylator (wiedza z analiz)","kb-yt-watch/review-judge":"weryfikator destylatów","kb-yt-watch/review-adversary":"adwokat diabła destylatów","kb-yt-watch/autopublish-judge":"sędzia autopublikacji","kb-ingest/questions":"pytania do chunków","kb-ingest/embed":"embeddingi chunków","kb-ingest/topics":"dodatkowe tagi z treści","kb-search/tutor":"odpowied
16ź tutora","kb-search/condense":"kondensacja pytania","kb-search/embed":"embedding pytania","kb-quiz/quiz":"quiz do lekcji","kb-tts/lektor-smooth":"wygładzenie tekstu pod lektora","kb-admin/search":"wyszukiwarka adminowa","kb-admin/mentor-bio":"bio mentora z transkryptu","kb-admin/embed":"embedding zapytania","kb-generate-script/writer":"skrypt: pisanie","kb-generate-script/editor":"skrypt: redaktor","kb-generate-script/short":"skrypt: short","kb-generate-script/dyspozytor":"skrypt: dyspozytor briefu","kb-generate-script/text":"skrypt: przebieg tekstowy","kb-generate-script/embed":"skrypt: embeddingi","kb-generate-course/lesson":"kurs: lekcja / wstęp","kb-generate-course/embed":"kurs: embeddingi","kb-generate-analysis/analysis":"asystent analiz: pisanie","kb-generate-analysis/embed":"asystent analiz: embedding","soft-analysis/ocena":"analiza miękka: 25 pytań z wyszukiwaniem","signal-interpret/przecena":"przecena: przyczyna z wyszukiwaniem i komentarzami mentorów","macro-comment/komentarz":"makro: komentarz AI","geo-hotspots/punkty":"geopolityka: punkty zapalne z komentarzy","company-analysis/analysis":"analiza spółki: pisanie","company-analysis/thesis":"analiza spółki: scenariusz","company-analysis/check":"analiza spółki: weryfikacja tezy","company-analysis/chat":"analiza spółki: czat z dokumentami","company-analysis/research":"analiza spółki: research z internetu","company-analysis/fact-sheet":"analiza spółki: karta liczb","company-analysis/guard":"analiza spółki: strażnik dossier","company-analysis/events":"analiza spółki: kalendarz zdarzeń","company-analysis/czuwanie":"analiza spółki: czuwanie (detektor)","company-analysis/ingest":"analiza spółki: wciąganie dokumentów","company-analysis/embed":"analiza spółki: embeddingi","company-report/report":"raport spółki","daily-brief/pisanie-cz1":"brief: pisanie, część 1","daily-brief/pisanie-cz2":"brief: pisanie, część 2","daily-brief/audytor":"brief: audytor","daily-brief/korektor":"brief: korektor","daily-brief/nastroje-tekst":"brief: omówienie nastrojów","yt-serwis/wiadomosci":"serwis: pisanie (wiadomości)","yt-serwis/nastroje":"serwis: pisanie (nastroje)","yt-serwis/embed":"serwis: embedding warsztatu","ai-categorize/categorize":"prywatny portfel: kategoryzacja","ai-merchant-info/merchant-info":"prywatny portfel: opis sprzedawcy","ai-restructure/restructure":"prywatny portfel: restrukturyzacja kategorii","prepare-import/describe":"prywatny portfel: opis transakcji","prepare-import/categories":"prywatny portfel: propozycja kategorii"};function gs(s,a){return js[`${s}/${a}`]??`${s} / ${a}`}const ws={login:"logowanie",logout:"wylogowanie",user_signedup:"rejestracja",user_repeated_signup:"ponowna próba rejestracji",user_recovery_requested:"reset hasła",user_confirmation_requested:"prośba o potwierdzenie e-maila",token_revoked:"unieważnienie sesji"},fs=s=>ws[s]??s,bs={events:[],logins:0,activeDays:0,lastLoginAt:null},ke=()=>({...bs,events:[]}),ne=s=>(s??"").trim().toLowerCase();function ks(s){var t;const a=[...s].sort((r,c)=>new Date(c.created_at).getTime()-new Date(r.created_at).getTime()),p=new Map,u=new Map;for(const r of a){const c=ne(r.email);if(!c)continue;const o=p.get(c)??ke();if(o.events.push(r),r.action==="login"){o.logins+=1,o.lastLoginAt||(o.lastLoginAt=r.created_at);const y=u.get(c)??new Set;y.add(new Date(r.created_at).toDateString()),u.set(c,y)}p.set(c,o)}for(const[r,c]of p)c.activeDays=((t=u.get(r))==null?void 0:t.size)??0;return p}const Z=()=>({calls:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,costUsd:0,unpricedCalls:0,functions:[]}),E=s=>{const a=typeof s=="string"?Number(s):s;return typeof a=="number"&&Number.isFinite(a)?a:0};function zs(s,a,p,u=new Date){const t=new Date(u.getTime()-(p-1)*864e5).toISOString().slice(0,10),r=new Map,c=Z(),o=Z(),y=new Map,j=(l,d)=>{l.calls+=E(d.calls),l.inputTokens+=E(d.input_tokens),l.outputTokens+=E(d.output_tokens),l.cacheReadTokens+=E(d.cache_read_tokens),l.cacheWriteTokens+=E(d.cache_write_tokens),l.costUsd+=E(d.est_cost_usd),l.unpricedCalls+=E(d.unpriced_calls);const m=y.get(l)??new Map,x=m.get(d.fn)??{calls:0,costUsd:0};
16x.calls+=E(d.calls),x.costUsd+=E(d.est_cost_usd),m.set(d.fn,x),y.set(l,m)};for(const l of s){if(!l.day||l.day<t)continue;if(!l.user_id){j(c,l);continue}const d=ne(a[l.user_id]??null);if(!d){j(o,l);continue}const m=r.get(d)??Z();j(m,l),r.set(d,m)}for(const[l,d]of y)l.functions=[...d.entries()].map(([m,x])=>({fn:m,...x})).sort((m,x)=>x.costUsd-m.costUsd||x.calls-m.calls||m.fn.localeCompare(x.fn));let n=c.costUsd+o.costUsd;for(const l of r.values())n+=l.costUsd;return{byEmail:r,unattributed:c,deletedAccounts:o,totalCostUsd:n}}const Ns=s=>s.inputTokens+s.outputTokens+s.cacheReadTokens+s.cacheWriteTokens;function vs(s,a,p=new Date){const u=p.toISOString().slice(0,10),t=new Map;for(const r of s){if(r.day!==u||!r.user_id)continue;const c=ne(a[r.user_id]??null);c&&t.set(c,(t.get(c)??0)+E(r.est_cost_usd))}return t}const re=1,Ss="[email protected]";function Ls(s){return(s??"").trim().toLowerCase()===Ss.toLowerCase()}const ce=s=>`${s.toFixed(2).replace(".",",")} $`;function Ts(s,a=re){return s===null?{allowed:!0,spentUsd:null,limitUsd:a,message:null,reason:"licznik-niedostepny"}:s<a?{allowed:!0,spentUsd:s,limitUsd:a,message:null,reason:"w-budzecie"}:{allowed:!1,spentUsd:s,limitUsd:a,reason:"limit",message:`Dzienny limit kosztów AI dla tego konta został wyczerpany: ${ce(s)} z ${ce(a)}. To nie jest awaria — licznik zeruje się o północy czasu UTC (1:00–2:00 w Polsce).`}}const As=1024,Cs=1150,Ps=3.3;function ze(s){const a=typeof s=="string"?s.trim().length:0;return Math.ceil(a/Ps)}function de(s){const a=ze(s);return a===0||a>=Cs?null:`Prompt ma ok. ${a} tokenów. Poniżej ${As} dostawca nie cache'uje prefiksu — każde wywołanie płaci pełną cenę wejścia. Skracanie tego promptu może kosztować więcej, niż oszczędza.`}const _s="[email protected]",ie=s=>s?new Date(s).toLocaleDateString("pl-PL",{day:"2-digit",month:"2-digit",year:"numeric"}):"—",O=s=>s?new Date(s).toLocaleString("pl-PL",{dateStyle:"short",timeStyle:"short"}):"—",Es=s=>s?new Date(s).toLocaleString("pl-PL",{dateStyle:"short",timeStyle:"medium"}):"—";function $a(){const[s,a]=_e("overview"),{user:p,loading:u}=ve();return u?null:!p||(p.email??"").trim().toLowerCase()!==_s?e.jsx(Se,{to:"/app",replace:!0}):e.jsxs("div",{className:"space-y-6",children:[e.jsx(Pe,{breadcrumb:["Admin"],title:"Panel administracyjny",subtitle:"Zarządzanie aplikacją: konta, pokrycie danych, import brokerów i zdrowie źródeł notowań."}),e.jsx(Ms,{}),e.jsx(Le,{children:e.jsx(Te,{className:"pt-6",children:e.jsxs(Ae,{value:s,onValueChange:a,className:"space-y-6",children:[e.jsxs(Ce,{className:"grid w-full grid-cols-2 sm:w-auto sm:inline-flex md:grid-cols-8",children:[e.jsxs(P,{value:"overview",className:"gap-2",children:[e.jsx(qe,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:"Przegląd"})]}),e.jsxs(P,{value:"users",className:"gap-2",children:[e.jsx(Ke,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:"Użytkownicy"})]}),e.jsxs(P,{value:"coverage",className:"gap-2",children:[e.jsx(Be,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:"Pokrycie danych"})]}),e.jsxs(P,{value:"tax",className:"gap-2",children:[e.jsx(Ze,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:"Podatki"})]}),e.jsxs(P,{value:"imports",className:"gap-2",children:[e.jsx(te,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:"Import brokerów"})]}),e.jsxs(P,{value:"integrations",className:"gap-2",children:[e.jsx(le,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:"Integracje"})]}),e.jsxs(P,{value:"health",className:"gap-2",children:[e.jsx(le,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:"Notowania / FX"})]}),e.jsxs(P,{value:"alerts",className:"gap-2",children:[e.jsx(ye,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:"Alerty"})]}),e.jsxs(P,{value:"prompts",className:"gap-2",children:[e.jsx(Qe,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:"Prompty"})]}),e.jsxs(P,{value:"models",className:"gap-2",children:[e.jsx(Re,{className:"h-4 w-4"}),e.jsx("span",{className:"hidden sm:inline",children:"Modele"})]})]}),e.jsx(_,{value:"overview",children:e.jsx(Us,{})}),e.jsx(_,{value:"users",children:e.jsx(Js,{})}),e.jsx(_,{value:"coverage",children:e.jsx(Os,{})}),e.jsx(_,{value:"tax",children:e.jsx(Fs,{})}),e.jsx(_,{value:"imports",children:e.jsx(Bs,{})}),e.jsx(_,{value:"integrations",children:e.jsx(Rs,{})}),e.jsx(_,{value:"health",children:e.jsx(Ws,{})}),e.jsx(_,{value:"alerts",children:e.jsx(Ys,{})}),e.jsx(_,{value:"prompts",children:e.jsx(na,{})}),e.jsx(_,{value:"models",children:e.jsx(aa,{})})]})})})]})}function D({error:s}){const a=s instanceof Error?s.message:String(s);return e.jsxs("div",{className:"rounded-lg border border-destructive/40 bg-destructive/5 p-4 text-sm text-destructive",children:["Nie udało się wczytać danych: ",a,". Sprawdź, czy edge function ",e.jsx("code",{children:"admin-stats"})," jest zdeployowana."]})}const Ds=[{key:"totalUsers",label:"Wszystkie konta"},{key:"new7d",label:"Nowi (7 dni)"},{key:"new30d",label:"Nowi (30 dni)"},{key:"active30d",label:"Aktywni (30 dni)"},{key:"withData",label:"Konta z transakcjami"},{key:"totalPortfolios",label:"Portfele"},{key:"totalTransactions",label:"Transakcje"}];function Us(){const{data:s,isLoading:a,error:p}=T({queryKey:["admin","overview"],queryFn:es,staleTime:6e4});return a?e.jsx("div",{className:"text-sm text-muted-foreground",children:"Ładowanie…"}):p?e.jsx(D,{error:p}
16):s?e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4",children:Ds.map(({key:u,label:t})=>e.jsxs("div",{className:"rounded-xl bg-surface-container-lowest p-4",children:[e.jsx("div",{className:"text-xs uppercase tracking-wide text-muted-foreground",children:t}),e.jsx("div",{className:"mt-1 text-2xl font-semibold tabular-nums",children:s.kpi[u].toLocaleString("pl-PL")})]},u))}),e.jsxs("div",{children:[e.jsxs("div",{className:"mb-2 flex items-center gap-2 text-sm font-semibold",children:[e.jsx(ye,{className:"h-4 w-4"})," Ostatnie rejestracje"]}),s.recent.length===0?e.jsx("div",{className:"text-sm text-muted-foreground",children:"Brak."}):e.jsx("ul",{className:"divide-y divide-border rounded-lg border border-border",children:s.recent.map((u,t)=>e.jsxs("li",{className:"flex items-center justify-between px-4 py-2 text-sm",children:[e.jsx("span",{className:"truncate",children:u.email||"(brak e-maila)"}),e.jsx("span",{className:"shrink-0 text-muted-foreground",children:ie(u.created_at)})]},`${u.email}-${t}`))})]})]}):null}function $s(){return e.jsx(ge,{className:"mx-auto h-4 w-4 text-emerald-600"})}function Y(){return e.jsx(pe,{className:"mx-auto h-4 w-4 text-destructive"})}function Os(){const[s,a]=L.useState(!1),{data:p,isLoading:u,error:t}=T({queryKey:["admin","coverage"],queryFn:as,staleTime:6e4});if(u)return e.jsx("div",{className:"text-sm text-muted-foreground",children:"Ładowanie…"});if(t)return e.jsx(D,{error:t});const r=(p==null?void 0:p.rows)??[],c=/^(LOKATA|REAL|CASH):/i,o=x=>c.test(x.ticker),y=x=>!o(x)&&(!x.hasHistory||!x.hasQuote||!x.hasClassification),j=s?r.filter(y):r,n=r.filter(y).length,l=r.filter(x=>!o(x)&&!x.hasHistory).length,d=r.filter(x=>!o(x)&&!x.hasQuote).length,m=r.filter(x=>!o(x)&&!x.hasClassification).length;return e.jsxs("div",{className:"space-y-4",children:[e.jsx("div",{className:"grid grid-cols-2 gap-3 sm:grid-cols-4",children:[{label:"Aktywa w użyciu",v:r.length},{label:"Bez cen historycznych",v:l},{label:"Bez notowania",v:d},{label:"Bez klasyfikacji",v:m}].map(x=>e.jsxs("div",{className:"rounded-xl bg-surface-container-lowest p-4",children:[e.jsx("div",{className:"text-xs uppercase tracking-wide text-muted-foreground",children:x.label}),e.jsx("div",{className:"mt-1 text-2xl font-semibold tabular-nums",children:x.v.toLocaleString("pl-PL")})]},x.label))}),e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:s,onChange:x=>a(x.target.checked)}),"Pokaż tylko braki (",n,")"]}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs(F,{children:[e.jsx(q,{children:e.jsxs(v,{children:[e.jsx(w,{children:"Ticker"}),e.jsx(w,{children:"Nazwa"}),e.jsx(w,{className:"text-right",children:"W portfelach"}),e.jsx(w,{className:"text-center",children:"Notowanie"}),e.jsx(w,{className:"text-center",children:"Ceny hist."}),e.jsx(w,{className:"text-right",children:"Ostatnia cena"}),e.jsx(w,{className:"text-center",children:"Klasyfikacja"}),e.jsx(w,{className:"text-right",children:"Dywidendy"})]})}),e.jsx(B,{children:j.map(x=>e.jsxs(v,{children:[e.jsx(g,{className:"font-medium",children:x.ticker}),e.jsx(g,{className:"max-w-[16rem] truncate text-muted-foreground",children:x.name??"—"}),e.jsx(g,{className:"text-right tabular-nums",children:x.usedByPortfolios}),e.jsx(g,{className:"text-center",children:x.hasQuote?e.jsx($s,{}):e.jsx(Y,{})}),e.jsx(g,{className:"text-center",children:x.hasHistory?e.jsx("span",{className:"tabular-nums text-xs text-muted-foreground",children:x.historyRows.toLocaleString("pl-PL")}):e.jsx(Y,{})}),e.jsx(g,{className:"text-right text-xs text-muted-foreground",children:ie(x.historyLastDate)}),e.jsx(g,{className:"text-center",children:x.hasClassification?e.jsx("span",{className:"text-xs text-muted-foreground",children:x.sector}):e.jsx(Y,{})}),e.jsx(g,{className:"text-right tabular-nums text-muted-foreground",children:x.dividendTx||"—"})]},x.ticker))})]})})]})}function V(s){return s===null?"—":s<60?`${s} min`:s<1440?`${Math.round(s/60)} h`:`${Math.round(s/1440)} d`}function Fs(){const s=K(),{data:a}=Ie(),[p,u]=L.useState(""),[t,r]=L.useState([]),[c,o]=L.useState(!1);L.useEffect(()=>{!a||c||(u(String(Math.round(a.belka*1e4)/100)),r(Object.entries(a.withholding).sort(([n],[l])=>n==="DEFAULT"?1:l==="DEFAULT"?-1:n.localeCompare(l)).map(([n,l])=>({country:n,pct:String(Math.round(l*1e4)/100)}))),o(!0))},[a,c]);const y=R({mutationFn:()=>{const n={};for(const{country:d,pct:m}of t){const x=d.trim().toUpperCase(),i=parseFloat(m.replace(",","."));x&&Number.isFinite(i)&&(n[x]=i/100)}n.DEFAULT||(n.DEFAULT=oe.withholding.DEFAULT);const l=parseFloat(p.replace(",","."))/100;return xs({belka:Number.isFinite(l)?l:oe.belka,withholding:n})},onSuccess:()=>{C.success("Stawki podatków zapisane."),s.invalidateQueries({queryKey:["app-settings","tax"]})},onError:n=>C.error(n.message)}),j=(n,l,d)=>r(m=>m.map((x,i)=>i===n?{...x,[l]:d}
16:x));return e.jsxs("div",{className:"max-w-xl space-y-5",children:[e.jsx("p",{className:"text-xs text-muted-foreground",children:'Podatek u źródła od dywidend — stawki per kraj notowania (założenie: brak podwójnego opodatkowania). Używane do szacowania netto z brutto dla dywidend pobranych z API (z pliku mamy realny podatek). „DEFAULT" to stawka dla krajów spoza listy. Belka = podatek od zysków kapitałowych (przełącznik P&L netto dla kont standardowych).'}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-xs font-semibold",children:"Podatek Belka (%)"}),e.jsx("input",{value:p,onChange:n=>u(n.target.value),inputMode:"decimal",className:"h-9 w-28 rounded-md border border-border bg-surface-container-lowest px-2 text-sm tabular-nums"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx("div",{className:"text-xs font-semibold",children:"Podatek u źródła od dywidend (%)"}),e.jsxs("div",{className:"space-y-1.5",children:[t.map((n,l)=>e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{value:n.country,onChange:d=>j(l,"country",d.target.value),className:"h-8 w-24 rounded-md border border-border bg-surface-container-lowest px-2 text-sm uppercase",placeholder:"US"}),e.jsx("input",{value:n.pct,onChange:d=>j(l,"pct",d.target.value),inputMode:"decimal",className:"h-8 w-24 rounded-md border border-border bg-surface-container-lowest px-2 text-sm tabular-nums",placeholder:"15"}),e.jsx("button",{onClick:()=>r(d=>d.filter((m,x)=>x!==l)),className:"text-muted-foreground hover:text-destructive","aria-label":"Usuń",children:e.jsx(pe,{className:"h-4 w-4"})})]},l)),e.jsx("button",{onClick:()=>r(n=>[...n,{country:"",pct:""}]),className:"text-xs text-primary hover:underline",children:"+ dodaj kraj"})]})]}),e.jsxs($,{disabled:y.isPending,onClick:()=>y.mutate(),children:[y.isPending?e.jsx(W,{className:"h-4 w-4 animate-spin"}):null,e.jsx("span",{className:y.isPending?"ml-1.5":"",children:"Zapisz"})]})]})}const qs=[{value:"xtb",label:"XTB"},{value:"dif",label:"DIF Broker"},{value:"saxo",label:"Saxo Bank"},{value:"exante",label:"Exante"},{value:"ibkr",label:"Interactive Brokers"}];function G({label:s,v:a}){return e.jsxs("div",{className:"rounded-lg bg-surface-container-lowest p-3",children:[e.jsx("div",{className:"text-xs uppercase tracking-wide text-muted-foreground",children:s}),e.jsx("div",{className:"mt-0.5 font-semibold tabular-nums break-words",children:a})]})}function Bs(){const[s,a]=L.useState("xtb"),[p,u]=L.useState(!1),[t,r]=L.useState(null),[c,o]=L.useState(null),y=(n,l)=>`${n.toLocaleString("pl-PL",{maximumFractionDigits:2})} ${l}`;async function j(n){u(!0),r(null),o(null);try{const l=await n.arrayBuffer(),d=await Me(l,s,n.name),m={};for(const h of d.positions)m[h.currency]=(m[h.currency]??0)+h.amount;const x=d.income??[],i={};for(const h of x)i[h.currency]=(i[h.currency]??0)+h.amount;o({fileName:n.name,kind:d.kind,positions:d.positions.length,cost:m,cash:d.cash.map(h=>({currency:h.currency,value:h.value})),divCount:x.length,divNet:i,warnings:d.warnings??[]})}catch(l){r(l.message)}finally{u(!1)}}return e.jsxs("div",{className:"space-y-5",children:[e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Podgląd parsera (sandbox) — wgraj plik eksportu brokera, by zobaczyć, co zostałoby zaimportowane. ",e.jsx("b",{children:"Nic nie zapisuje do bazy."})," Przydatne, gdy broker zmieni format eksportu — od razu widać, czy parser go obsługuje."]}),e.jsxs("div",{className:"flex flex-wrap items-end gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{className:"text-xs font-semibold",children:"Broker"}),e.jsx("select",{value:s,onChange:n=>a(n.target.value),className:"h-9 w-44 rounded-md border border-border bg-surface-container-lowest px-2 text-sm",children:qs.map(n=>e.jsx("option",{value:n.value,children:n.label},n.value))})]}),e.jsxs("label",{className:"inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-md border border-dashed border-border px-3 text-sm hover:bg-surface-container",children:[e.jsx(te,{className:"h-4 w-4"})," Wgraj plik (.xlsx / .xls / .csv)",e.jsx("input",{type:"file",accept:".xlsx,.xls,.csv",className:"hidden",onChange:n=>{var d;const l=(d=n.target.files)==null?void 0:d[0];l&&j(l),n.target.value=""}})]}),p&&e.jsx(W,{className:"h-4 w-4 animate-spin text-muted-foreground"})]}),t&&e.jsxs("div",{className:"rounded-lg border border-destructive/40 bg-destructive/5 p-3 text-sm text-destructive",children:["Błąd parsowania: ",t]}),c&&e.jsxs("div",{className:"space-y-3 rounded-xl border border-border p-4",children:[e.jsxs("div",{className:"text-sm font-semibold",children:[c.fileName," ",e.jsxs("span",{className:"font-normal text-muted-foreground",children:["· ",c.kind]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3 sm:grid-cols-4",children:[e.jsx(G,{label:"Pozycje",v:String(c.positions)}),e.jsx(G,{label:"Wiersze dywidend",v:String(c.divCount)}),e.jsx(G,{label:"Koszt",v:Object.entries(c.cost).map(([n,l])=>y(l,n)).join(" · ")||"—"}),e.jsx(G,{label:"Gotówka",v:c.cash.map(n=>
16y(n.value,n.currency)).join(" · ")||"—"})]}),Object.keys(c.divNet).length>0&&e.jsxs("div",{className:"text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Dywidendy netto: "}),Object.entries(c.divNet).map(([n,l])=>y(l,n)).join(" · ")]}),c.warnings.length>0&&e.jsx("div",{className:"rounded-lg border border-amber-500/40 bg-amber-500/5 p-2 text-xs text-amber-600",children:c.warnings.map((n,l)=>e.jsxs("div",{children:["⚠ ",n]},l))})]}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:["Status wzorców (golden): ",e.jsx("b",{children:"XTB, DIF, Exante, Saxo PLN, Saxo USD"})," — zatwierdzone ·",e.jsx("b",{children:" IBKR"})," — WIP (do walidacji). Pliki wzorcowe:",e.jsx("code",{children:" broker-import-samples/"}),"."]})]})}const I={ok:{dot:"bg-emerald-500",label:"OK"},warn:{dot:"bg-amber-500",label:"Uwaga"},down:{dot:"bg-destructive",label:"Awaria"}},Is={ok:{cls:"border-emerald-500/40 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400",label:"Wszystko działa"},warn:{cls:"border-amber-500/40 bg-amber-500/10 text-amber-600 dark:text-amber-400",label:"Wymaga uwagi"},down:{cls:"border-destructive/40 bg-destructive/10 text-destructive",label:"Awaria — sprawdź"}};function Ne(){const s=T({queryKey:["admin","health"],queryFn:we,staleTime:3e4}),a=T({queryKey:["admin","errors"],queryFn:fe,staleTime:3e4}),p=Ve(s.data,a.data);return{items:p,status:Je(p),loading:s.isLoading||a.isLoading,error:s.error||a.error}}function Ms(){const{items:s,status:a,loading:p,error:u}=Ne();if(p)return null;if(u)return e.jsxs("div",{className:"flex flex-wrap items-center gap-x-3 gap-y-1 rounded-xl border border-muted-foreground/30 bg-muted/30 px-4 py-3 text-sm",children:[e.jsx("span",{className:"h-2.5 w-2.5 rounded-full bg-muted-foreground/50"}),e.jsx("span",{className:"font-semibold",children:"Status systemu niedostępny"}),e.jsxs("span",{className:"text-muted-foreground",children:["Nie udało się wczytać danych panelu — sprawdź, czy edge function ",e.jsx("code",{children:"admin-stats"})," jest zdeployowana."]})]});const t=s.filter(c=>c.status!=="ok").map(c=>c.name),r=Is[a];return e.jsxs("div",{className:M("rounded-xl border px-4 py-3 flex flex-wrap items-center gap-x-3 gap-y-1 text-sm",r.cls),children:[e.jsx("span",{className:M("h-2.5 w-2.5 rounded-full",I[a].dot)}),e.jsx("span",{className:"font-semibold",children:r.label}),e.jsx("span",{className:"text-muted-foreground",children:a==="ok"?"Wszystkie integracje sprawne.":`Do sprawdzenia: ${t.join(", ")}.`})]})}const Ks={"Notowania (ceny)":"Część tickerów się nie odświeża — niektóre wyceny mogą być nieaktualne. Najpierw kliknij „Odśwież notowania” w zakładce Notowania / FX. Tickery uporczywie nieaktualne (giełdy spoza USA, fundusze OTC) mogą nie być obsługiwane przez dostawców — sprawdź ich symbol w „Pokrycie danych”.","Kursy walut (FX)":"Kursy walut się nie odświeżają — przeliczenia na PLN mogą być nieprecyzyjne (w użyciu kursy awaryjne). Sprawdź kartę „Kursy walut” na pulpicie.","Cron notowań (refresh-quotes)":"Cykliczne odświeżanie notowań mogło przestać działać (cache nie był aktualizowany). Uruchom ręcznie „Odśwież notowania” w zakładce Notowania / FX i sprawdź zadanie cron w Supabase.","Strażnik danych (data-health)":"Codzienny strażnik danych dawno nie raportował — mógł przestać się uruchamiać (cron lub Resend). Sprawdź konfigurację zadania cron w Supabase.","Import / backfill":"Któryś import lub backfill zakończył się błędem w ostatnich 24h. Szczegóły i wyjaśnienie w zakładce Alerty.","Baza danych (Supabase)":"Brak odpowiedzi z bazy — pozostałe dane panelu mogą się nie ładować."};function Rs(){const{items:s,error:a,loading:p}=Ne();if(p)return e.jsx("div",{className:"text-sm text-muted-foreground",children:"Ładowanie…"});if(a)return e.jsx(D,{error:a});const u=s.filter(t=>t.status!=="ok");return e.jsxs("div",{className:"space-y-4",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:'Stan połączeń z usługami zewnętrznymi (ceny, FX, crony, baza). Wyliczane z cache notowań i logu błędów — bez osobnego zapytania. „Awaria/Uwaga" tu = sprawdź log w zakładce Alerty.'}),e.jsx("div",{className:"overflow-hidden rounded-xl border border-outline-variant/20",children:e.jsxs(F,{children:[e.jsx(q,{children:e.jsxs(v,{children:[e.jsx(w,{children:"Integracja"}),e.jsx(w,{children:"Status"}),e.jsx(w,{children:"Szczegóły"}),e.jsx(w,{children:"Ostatni OK"}),e.jsx(w,{className:"text-right",children:"Błędy 24h"})]})}),e.jsx(B,{children:s.map(t=>e.jsxs(v,{children:[e.jsx(g,{className:"font-medium",children:t.name}),e.jsx(g,{children:e.jsxs("span",{className:"inline-flex items-center gap-2",children:[e.jsx("span",{className:M("h-2.5 w-2.5 rounded-full",I[t.status].dot)}),I[t.status].label]})}),e.jsx(g,{className:"text-muted-foreground",children:t.detail}),e.jsx(g,{className:"text-muted-foreground",children:t.lastOk?O(t.lastOk):"—"}),e.jsx(g,{className:M("text-right tabular-nums",t.errors24h>0&&"text-destructive"),children:t.errors24h})]},t.name))})]})}),u.length===0?e.jsx("div",{className:"rounded-xl border border-emerald-500/30 bg-emerald-500/5 p-4 text-sm text-emerald-700 dark:text-emerald-400",children:"Wszystkie integracje działają poprawnie — nic nie wymaga uwagi."}):e.jsxs("div",{className:"rounded-xl border border-outline-variant/20 bg-surface-container-lowest p-4",children:[e.jsxs("div",{className:"mb-3 flex items-center gap-2 text-sm font-semibold",children:[e.jsx(ae,{className:"h-4 w-4"})," Co wymaga uwagi i co z tym zrobić"]}),e.jsx("ul",{className:"space-y-3",children:u.map(t=>e.jsxs("li",{className:"text-sm",children:[e.jsxs("span",{className:"inline-flex items-center gap-2 font-medium",children:[e.jsx("span",{className:M("h-2.5 w-2.5 rounded-full",I[t.status].dot)}),t.name," — ",I[t.status].label,"."]})," ",e.jsx("span",{className:"text-muted-foreground",children:Ks[t.name]??"Sprawdź szczegóły w zakładce Alerty."})]},t.name))})]})]})}function Ws(){const s=K(),{data:a,isLoading:p,error:u}=T({queryKey:["admin","health"],queryFn:we,staleTime:3e4}),t=R({mutationFn:us,onSuccess:()=>{C.success("Odświeżanie notowań uruchomione."),setTimeout(()=>s.invalidateQueries({queryKey:["admin","health"]}),3e3)},onError:r=>C.error(r.message)});return p?e.jsx("div",{className:"text-sm text-muted-foreground",children:"Ładowanie…"}):u?e.jsx(D,{error:u}):a?e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Serwerowy cache notowań (",e.jsx("code",{children:"quote_cache"}),"). Liczby dotyczą ",e.jsx("strong",{children:"śledzonych"}),' tickerów (trzymane ∪ obserwowane ∪ indeksy) — „Nieaktualne" = starsze niż ',a.staleMinutes,' min. Wiersze dla tickerów, których nikt już nie trzyma/obserwuje, liczone są jako „Osierocone" i nie alarmują. Kursy walut (FX) są liczone po stronie klienta (Frankfurter/ECB + fallback) — nie ma ich tutaj.']}),e.jsxs($,{size:"sm",variant:"outline",disabled:t.isPending,onClick:()=>t.mutate(),children:[t.isPending?e.jsx(W,{className:"h-4 w-4 animate-spin"}):e.jsx(We,{className:"h-4 w-4"}),e.jsx("span",{className:"ml-1.5",children:"Odśwież notowania"})]})]}),e.jsx("div",{className:"grid grid-cols-2 gap-3 sm:grid-cols-6",children:[{label:"Śledzone w cache",v:String(a.total)},{label:"Świeże",v:String(a.fresh)},{label:"Nieaktualne",v:String(a.stale)},{label:"Osierocone",v:String(a.orphaned??0)},{label:"Najstarszy",v:V(a.oldestMin)},{label:"Kursy walut (FX)",v:a.fxAgeMin===null?"—":V(a.fxAgeMin)}].map(r=>e.jsxs("div",{className:"rounded-xl bg-surface-container-lowest p-4",children:[e.jsx("div",{className:"text-xs uppercase tracking-wide text-muted-foreground",children:r.label}),e.jsx("div",{className:"mt-1 text-2xl font-semibold tabular-nums",children:r.v})]},r.label))}),a.missing.length>0&&e.jsxs("div",{className:"rounded-lg border border-amber-500/40 bg-amber-500/5 p-3 text-sm",children:[e.jsxs("div",{className:"font-semibold text-amber-600",children:["Tickery w portfelach bez żadnego notowania (",a.missing.length,")"]}),e.jsx("div",{className:"mt-1 text-xs text-muted-foreground break-words",children:a.missing.join(", ")})]}),e.jsxs("div",{children:[e.jsx("div",{className:"mb-2 text-sm font-semibold",children:"Najbardziej nieaktualne notowania"}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs(F,{children:[e.jsx(q,{children:e.jsxs(v,{children:[e.jsx(w,{children:"Ticker"}),e.jsx(w,{children:"Nazwa"}),e.jsx(w,{className:"text-right",children:"Wiek"}),e.jsx(w,{children:"Pobrano"})]})}),e.jsx(B,{children:a.stalest.map(r=>e.jsxs(v,{children:[e.jsx(g,{className:"font-medium",children:r.ticker}),e.jsx(g,{className:"max-w-[16rem] truncate text-muted-foreground",children:r.name??"—"}),e.jsx(g,{className:"text-right tabular-nums",children:V(r.ageMin)}),e.jsx(g,{className:"text-muted-foreground",children:O(r.fetchedAt)})]},r.ticker))})]})})]}),e.jsx(Xs,{})]}):null}const Hs={finnhub:"Finnhub",yahoo:"Yahoo",stooq:"Stooq",fmp:"FMP",alphavantage:"Alpha Vantage",frankfurter:"Frankfurter (FX)"};function Xs(){const{data:s,isLoading:a,error:p}=T({queryKey:["admin","provider-usage"],queryFn:ms,staleTime:6e4}),u=(s==null?void 0:s.providers)??[];return e.jsxs("div",{children:[e.jsx("div",{className:"mb-2 text-sm font-semibold",children:"Zużycie dostawców danych (dziś / 7 dni)"}),e.jsxs("p",{className:"mb-2 text-xs text-muted-foreground",children:["Liczba zapytań do zewnętrznych API. Tylko FMP i Alpha Vantage mają sensowny limit",e.jsx("b",{children:" dzienny"})," — przy nich pokazujemy % wykorzystania. Finnhub ma limit minutowy (60/min), a Yahoo/Stooq/Frankfurter nie mają twardego dziennego limitu (sam wolumen)."]}),a?e.jsx("div",{className:"text-sm text-muted-foreground",children:"Ładowanie…"}):p?e.jsx(D,{error:p}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs(F,{children:[e.jsx(q,{children:e.jsxs(v,{children:[e.jsx(w,{children:"Dostawca"}),e.jsx(w,{className:"text-right",children:"Dziś"}),e.jsx(w,{className:"text-right",children:"7 dni"}),e.jsx(w,{className:"text-right",children:"Limit dzienny"}),e.jsx(w,{className:"text-right",children:"% limitu"}),e.jsx(w,{children:"Uwaga"})]})}),e.jsx(B,{children:u.map(t=>{var o;const r=t.pctOfLimit!=null&&t.pctOfLimit>=80,c=t.pctOfLimit!=null&&t.pctOfLimit>=50&&t.pctOfLimit<80;return e.jsxs(v,{children:[e.jsx(g,{className:"font-medium",children:Hs[t.provider]??t.provider}),e.jsx(g,{className:"text-right tabular-nums",children:t.today.toLocaleStr
16ing("pl-PL")}),e.jsx(g,{className:"text-right tabular-nums text-muted-foreground",children:t.last7d.toLocaleString("pl-PL")}),e.jsx(g,{className:"text-right tabular-nums text-muted-foreground",children:((o=t.dailyLimit)==null?void 0:o.toLocaleString("pl-PL"))??"—"}),e.jsx(g,{className:`text-right tabular-nums font-semibold ${r?"text-destructive":c?"text-amber-600":""}`,children:t.pctOfLimit!=null?`${t.pctOfLimit}%`:"—"}),e.jsx(g,{className:"max-w-[20rem] truncate text-xs text-muted-foreground",title:t.note,children:t.note})]},t.provider)})})]})})]})}const Gs={add:"Dodano",replace:"Zastąpiono",consolidate:"Konsolidacja",migrate:"Migracja"},ee={import_failed:{label:"Nieudany import",meaning:"Import pliku z brokera przerwał się — część danych mogła nie zostać zapisana.",action:"Sprawdź plik źródłowy i zaimportuj ponownie. Jeśli błąd się powtarza, broker mógł zmienić format pliku."},backfill_failed:{label:"Nieudany backfill",meaning:"Uzupełnianie historii cen lub dywidend dla tickera się nie powiodło.",action:"Zwykle chwilowy problem dostawcy danych — spróbuj odświeżyć notowania później. Jeśli stałe, sprawdź ticker w zakładce „Pokrycie danych”."},parse_failed:{label:"Błąd parsowania pliku",meaning:"Nie udało się odczytać struktury pliku brokera (zmieniony format lub uszkodzony plik).",action:"Upewnij się, że to oryginalny eksport z brokera. Jeśli broker zmienił format eksportu, trzeba zaktualizować parser."},quote_failed:{label:"Brak notowań (dostawca cen)",meaning:"Żaden dostawca cen nie odpowiedział (Yahoo/Stooq przez proxy). Wyceny pozycji mogą być nieaktualne.",action:"Najczęściej chwilowa awaria zewnętrzna — zerknij na zakładkę „Integracje”. Jeśli trwa ponad 30 min, sprawdź proxy/sieć."},fx_failed:{label:"Brak kursów walut (FX)",meaning:"Wszyscy dostawcy kursów (Frankfurter/ECB) są niedostępni — w użyciu kursy awaryjne (zaszyte w kodzie).",action:"Przeliczenia na PLN mogą być nieprecyzyjne. Sprawdź kartę „Kursy walut” na pulpicie — gdy FX wróci, alert zniknie sam."},exception:{label:"Wyjątek aplikacji",meaning:"Nieoczekiwany błąd, który nie pasuje do pozostałych kategorii.",action:"Zobacz treść komunikatu w kolumnie obok. Jeśli się powtarza, warto zajrzeć w logi/konsolę przeglądarki."}},me=Object.fromEntries(Object.entries(ee).map(([s,a])=>[s,a.label]));function Qs(s){const a=s??{},p=[],u=j=>Array.isArray(j)?j:[];a.fxOk===!1&&p.push("Kursy walut: dostawca FX (Frankfurter/ECB) nie odpowiada — przeliczenia w
16alut po sztywnych kursach awaryjnych.");const t=u(a.stillStale);if(t.length>0){const j=t.map(n=>n==null?void 0:n.ticker).filter(Boolean).slice(0,12).join(", ");p.push(`Nieświeże ceny (nie do auto-naprawy): ${t.length} — ${j}${t.length>12?"…":""}.`)}const r=u(a.quoteGaps);r.length>0&&p.push(`Brak świeżej wyceny → liczone po koszcie zakupu („płaski" portfel): ${r.length} — ${r.slice(0,12).join(", ")}${r.length>12?"…":""}. Najczęściej zatrzymany cron refresh-quotes.`);const c=u(a.indexIssues);if(c.length>0){const j=c.map(n=>n==null?void 0:n.ticker).filter(Boolean).join(", ");p.push(`Rynki — nieświeża historia (dzienny % liczony od starego zamknięcia): ${j}.`)}const o=Number(a.errorCount??0);if(o>0){const j=a.errorsByKind??{},n=Object.entries(j).map(([l,d])=>`${l}: ${d}`).join(", ");p.push(`Błędy aplikacji (24h): ${o}${n?` (${n})`:""} — szczegóły w tabeli poniżej.`)}const y=u(a.providerWarnings);return y.length>0&&p.push(`Limity dostawców danych: ${y.join(", ")}.`),p}function Zs({health:s}){if(!s)return e.jsxs("div",{className:"rounded-lg border border-amber-500/40 bg-amber-500/5 p-3 text-sm",children:[e.jsxs("div",{className:"flex items-center gap-2 font-semibold text-amber-600",children:[e.jsx(J,{className:"h-4 w-4"})," Strażnik danych jeszcze nie raportował"]}),e.jsxs("div",{className:"mt-1 text-xs text-muted-foreground",children:["Funkcja ",e.jsx("code",{children:"data-health"})," (codzienny cron + e-mail przez Resend) nie zapisała jeszcze żadnego przebiegu do ",e.jsx("code",{children:"system_health"}),". Sprawdź, czy jest zdeployowana i ma ustawiony cron."]})]});const a=s.ok,p=a?[]:Qs(s.report);return e.jsxs("div",{className:`rounded-lg border p-3 text-sm ${a?"border-emerald-500/40 bg-emerald-500/5":"border-destructive/40 bg-destructive/5"}`,children:[e.jsxs("div",{className:`flex items-center gap-2 font-semibold ${a?"text-emerald-600":"text-destructive"}`,children:[a?e.jsx(je,{className:"h-4 w-4"}):e.jsx(J,{className:"h-4 w-4"}),a?"Dane zdrowe (ostatni przebieg strażnika)":"Strażnik danych zgłosił problem"]}),e.jsxs("div",{className:"mt-1 text-xs text-muted-foreground",children:["Ostatni przebieg ",e.jsx("code",{children:"data-health"}),": ",O(s.createdAt),".",a?" Ceny świeże, FX dostępny, wszystkie pozycje wyceniane na żywo.":" Alert poszedł też mailem."]}),p.length>0&&e.jsx("ul",{className:"mt-2 space-y-1 text-xs text-destructive",children:p.map((u,t)=>e.jsxs("li",{className:"flex gap-1.5",children:[e.jsx("span",{"aria-hidden":!0,children:"•"}),e.jsx("span",{children:u})]},t))}),!a&&p.length===0&&e.jsx("div",{className:"mt-1 text-xs text-muted-foreground",children:"Szczegóły w mailu (strażnik zgłosił problem, ale brak rozbicia w raporcie)."})]})}function Ys(){var o,y,j;const s=K(),a=T({queryKey:["admin","errors"],queryFn:fe,staleTime:3e4}),p=R({mutationFn:ps,onSuccess:n=>{var l,d,m,x;if(n.ok)C.success("Strażnik: wszystko OK — ceny świeże, FX dostępny, wszystkie pozycje wyceniane na żywo.");else{const i=n.report??{},h=[];i.fxOk===!1&&h.push("FX niedostępny"),(((l=i.quoteGaps)==null?void 0:l.length)??0)>0&&h.push(`${i.quoteGaps.length} bez świeżej wyceny`),(((d=i.indexIssues)==null?void 0:d.length)??0)>0&&h.push(`${i.indexIssues.length} rynków: nieświeża historia`),(((m=i.stillStale)==null?void 0:m.length)??0)>0&&h.push(`${i.stillStale.length} nieświeżych cen`),(i.errorCount??0)>0&&h.push(`${i.errorCount} błędów 24h`),(((x=i.providerWarnings)==null?void 0:x.length)??0)>0&&h.push("limity dostawców"),C.error(`Strażnik wykrył problemy: ${h.join(", ")||"patrz panel"}.${n.emailed?" Wysłano e-mail.":""}`)}s.invalidateQueries({queryKey:["admin","errors"]})},onError:n=>C.error(`Nie udało się uruchomić strażnika: ${n.message}`)});if(a.isLoading)return e.jsx("div",{className:"text-sm text-muted-foreground",children:"Ładowanie…"});if(a.error)return e.jsx(D,{error:a.error});const u=((o=a.data)==null?void 0:o.errors)??[],t=((y=a.data)==null?void 0:y.last24h)??{},r=((j=a.data)==null?void 0:j.health)??null,c=u.length;return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Observability: zdrowie danych (codzienny strażnik ",e.jsx("code",{children:"data-health"})," + e-mail przez Resend), log błędów aplikacji (",e.jsx("code",{children:"app_errors"})," — nieudane importy/backfille/wyjątki) i log udanych importów brokerów."]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("span",{className:"text-xs font-semibold uppercase tracking-wide text-muted-foreground",children:"Strażnik danych (data-health)"}),e.jsxs($,{size:"sm",variant:"outline",disabled:p.isPending,onClick:()=>p.mutate(),children:[p.isPending?e.jsx(W,{className:"h-4 w-4 animate-spin"}):e.jsx(je,{className:"h-4 w-4"}),e.jsx("span",{className:"ml-1.5",children:p.isPending?"Sprawdzam…":"Uruchom strażnika teraz"})]})]}),e.jsx(Zs,{health:r})]}),e.jsx("div",{className:"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-6",children:["import_failed","backfill_failed","parse_failed","quote_failed","fx_failed","exception"].map(n=>e.jsxs("div",{className:"rounded-xl bg-surface-container-lowest p-4",children:[e.jsxs("div",{className:"text-xs uppercase tracking-wide text-muted-foreground",children:[me[n]," (24h)"]}),e.jsx("div",{className:`mt-1 text-2xl font-semibold tabular-nums ${(t[n]??0)>0?"text-destructive":""}
16`,children:(t[n]??0).toLocaleString("pl-PL")})]},n))}),(()=>{const n=Array.from(new Set(u.map(l=>l.kind))).filter(l=>ee[l]);return n.length===0?null:e.jsxs("div",{className:"rounded-xl border border-outline-variant/20 bg-surface-container-lowest p-4",children:[e.jsxs("div",{className:"mb-3 flex items-center gap-2 text-sm font-semibold",children:[e.jsx(ae,{className:"h-4 w-4"})," Co oznaczają te błędy"]}),e.jsx("ul",{className:"space-y-3",children:n.map(l=>{const d=ee[l];return e.jsxs("li",{className:"text-sm",children:[e.jsxs("span",{className:"font-medium text-destructive",children:[d.label,"."]})," ",e.jsx("span",{className:"text-foreground",children:d.meaning})," ",e.jsxs("span",{className:"text-muted-foreground",children:["→ ",d.action]})]},l)})})]})})(),e.jsxs("div",{children:[e.jsxs("div",{className:"mb-2 flex items-center gap-2 text-sm font-semibold",children:[e.jsx(J,{className:"h-4 w-4"})," Błędy aplikacji (",c,")"]}),u.length===0?e.jsx("div",{className:"rounded-lg border border-dashed border-border p-6 text-center text-sm text-muted-foreground",children:"Brak zarejestrowanych błędów. 🎉"}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs(F,{children:[e.jsx(q,{children:e.jsxs(v,{children:[e.jsx(w,{children:"Data"}),e.jsx(w,{children:"Konto"}),e.jsx(w,{children:"Typ"}),e.jsx(w,{children:"Źródło"}),e.jsx(w,{children:"Komunikat"})]})}),e.jsx(B,{children:u.map(n=>e.jsxs(v,{children:[e.jsx(g,{className:"whitespace-nowrap text-muted-foreground",children:O(n.createdAt)}),e.jsx(g,{className:"font-medium",children:n.email||"—"}),e.jsx(g,{children:e.jsx("span",{className:"text-destructive",children:me[n.kind]??n.kind})}),e.jsx(g,{className:"text-muted-foreground",children:n.source}),e.jsx(g,{className:"max-w-[24rem] truncate",title:n.message,children:n.message})]},n.id))})]})})]}),e.jsx(Vs,{})]})}function Vs(){const{data:s,isLoading:a,error:p}=T({queryKey:["admin","imports"],queryFn:ds,staleTime:3e4}),u=(s==null?void 0:s.imports)??[];return e.jsxs("div",{children:[e.jsxs("div",{className:"mb-2 flex items-center gap-2 text-sm font-semibold",children:[e.jsx(te,{className:"h-4 w-4"})," Log importów brokerów (",u.length,")"]}),a?e.jsx("div",{className:"text-sm text-muted-foreground",children:"Ładowanie…"}):p?e.jsx(D,{error:p}):u.length===0?e.jsx("div",{className:"rounded-lg border border-dashed border-border p-8 text-center text-sm text-muted-foreground",children:"Brak zarejestrowanych importów."}):e.jsx("div",{className:"overflow-x-auto",children:e.jsxs(F,{children:[e.jsx(q,{children:e.jsxs(v,{children:[e.jsx(w,{children:"Data"}),e.jsx(w,{children:"Konto"}),e.jsx(w,{children:"Portfel"}),e.jsx(w,{children:"Broker"}),e.jsx(w,{children:"Tryb"}),e.jsx(w,{children:"Plik"}),e.jsx(w,{className:"text-right",children:"Wiersze"})]})}),e.jsx(B,{children:u.map((t,r)=>e.jsxs(v,{children:[e.jsx(g,{className:"whitespace-nowrap text-muted-foreground",children:O(t.importedAt)}),e.jsx(g,{className:"font-medium",children:t.email||"(brak)"}),e.jsx(g,{className:"max-w-[12rem] truncate",children:t.portfolio||"—"}),e.jsx(g,{className:"uppercase",children:t.broker||"—"}),e.jsxs(g,{children:[Gs[t.mode]??t.mode??"—",t.kind?e.jsxs("span",{className:"text-muted-foreground",children:[" · ",t.kind]}):null]}),e.jsx(g,{className:"max-w-[14rem] truncate text-muted-foreground",children:t.fileName??"—"}),e.jsx(g,{className:"text-right tabular-nums",children:t.rowCount.toLocaleString("pl-PL")})]},`${t.importedAt}-${r}`))})]})})]})}function Js(){var d,m,x;const[s,a]=L.useState(null),{data:p,isLoading:u,error:t}=T({queryKey:["admin","users"],queryFn:ss,staleTime:6e4}),r=T({queryKey:["admin","logins"],queryFn:()=>ls(90),staleTime:6e4,retry:!1}),c=T({queryKey:["admin","ai-usage-users"],queryFn:()=>cs(30),staleTime:6e4,retry:!1});if(u)return e.jsx("div",{className:"text-sm text-muted-foreground",children:"Ładowanie…"});if(t)return e.jsx(D,{error:t});const o=(p==null?void 0:p.users)??[],y=ks(((d=r.data)==null?void 0:d.events)??[]),j=c.data?zs(c.data.rows,c.data.emails,30):null,n=new Set(o.map(i=>(i.email??"").trim().toLowerCase())),l=c.data?vs(c.data.rows,c.data.emails):null;return e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"text-sm text-muted-foreground",children:[o.length.toLocaleStr
16ing("pl-PL")," kont"]}),r.error&&e.jsxs("p",{className:"text-xs text-error",children:["Historia logowań niedostępna: ",r.error instanceof Error?r.error.message:String(r.error)]}),((m=r.data)==null?void 0:m.available)&&r.data.events.length===0&&e.jsxs("p",{className:"text-xs text-amber-700 dark:text-amber-400",children:["Supabase nie oddał ANI JEDNEGO wpisu z ostatnich ",r.data.days," dni. To nie znaczy, że nikt się nie logował — znaczy, że dziennik zdarzeń jest pusty (krótka retencja u dostawcy albo świeżo zaaplikowana migracja)."]}),c.error&&e.jsxs("p",{className:"text-xs text-error",children:["Zużycie AI per konto niedostępne: ",c.error instanceof Error?c.error.message:String(c.error)]}),e.jsxs("p",{className:"text-xs text-on-surface-variant",children:["Logowania liczone z dziennika Supabase Auth za ostatnie ",((x=r.data)==null?void 0:x.days)??90," dni;"," ",e.jsx("b",{children:"odświeżenia sesji nie są liczone"})," (przeglądarka robi je sama przy każdym powrocie na kartę i zasypałyby prawdziwe wejścia). Koszt AI to szacunek z cennika w kodzie za ostatnie 30 dni — prawdą są tokeny, dokładny rachunek jest u dostawcy."]}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs(F,{children:[e.jsx(q,{children:e.jsxs(v,{children:[e.jsx(w,{className:"w-8"}),e.jsx(w,{children:"E-mail"}),e.jsx(w,{children:"Rejestracja"}),e.jsx(w,{children:"Ostatnie logowanie"}),e.jsx(w,{className:"text-right",children:"Logowań (90 dni)"}),e.jsx(w,{className:"text-right",children:"Dni z wejściem"}),e.jsx(w,{className:"text-right",children:"Wywołania AI (30 dni)"}),e.jsx(w,{className:"text-right",children:"Tokeny (30 dni)"}),e.jsx(w,{className:"text-right",children:"Koszt AI (30 dni)"}),e.jsx(w,{className:"text-right",children:"Dziś / limit"}),e.jsx(w,{className:"text-right",children:"Portfele"}),e.jsx(w,{className:"text-right",children:"Transakcje"})]})}),e.jsx(B,{children:o.map((i,h)=>{const f=(i.email??"").trim().toLowerCase(),k=y.get(f)??ke(),b=j==null?void 0:j.byEmail.get(f),S=s===f;return e.jsxs(L.Fragment,{children:[e.jsxs(v,{className:k.events.length>0?"cursor-pointer":void 0,onClick:()=>k.events.length>0&&a(S?null:f),children:[e.jsx(g,{className:"text-muted-foreground",children:k.events.length>0?S?e.jsx(He,{className:"h-4 w-4"}):e.jsx(Xe,{className:"h-4 w-4"}):null}),e.jsx(g,{className:"font-medium",children:i.email||"(brak)"}),e.jsx(g,{className:"whitespace-nowrap",children:O(i.created_at)}),e.jsx(g,{className:"whitespace-nowrap",children:O(i.last_sign_in_at)}),e.jsx(g,{className:"text-right tabular-nums",children:r.isSuccess?k.logins.toLocaleString("pl-PL"):"—"}),e.jsx(g,{className:"text-right tabular-nums",children:r.isSuccess?k.activeDays.toLocaleString("pl-PL"):"—"}),e.jsx(g,{className:"text-right tabular-nums",children:c.isSuccess?((b==null?void 0:b.calls)??0).toLocaleString("pl-PL"):"—"}),e.jsx(g,{className:"text-right tabular-nums",children:c.isSuccess&&b?Ns(b).toLocaleString("pl-PL"):c.isSuccess?"0":"—"}),e.jsxs(g,{className:"text-right tabular-nums",children:[c.isSuccess?A((b==null?void 0:b.costUsd)??0):"—",b&&b.unpricedCalls>0&&e.jsx("span",{className:"text-amber-700 dark:text-amber-400",title:`${b.unpricedCalls} wywołań bez ceny w cenniku — koszt jest zaniżony`,children:" !"})]}),e.jsx(g,{className:"text-right tabular-nums whitespace-nowrap",children:l?e.jsx(ea,{email:f,spentToday:l.get(f)??0}):"—"}),e.jsx(g,{className:"text-right tabular-nums",children:i.portfolios}),e.jsx(g,{className:"text-right tabular-nums",children:i.transactions})]}),S&&e.jsx(v,{children:e.jsx(g,{colSpan:12,className:"bg-surface-variant/20",children:e.jsxs("div",{className:"space-y-2 py-1",children:[b&&b.functions.length>0&&e.jsxs("p",{className:"text-xs text-on-surface-variant",children:[e.jsx("b",{children:"Gdzie wydał:"})," ",b.functions.map(z=>`${be(z.fn)} ${A(z.costUsd)} (${z.calls}×)`).join(" · ")]}),e.jsx("div",{className:"max-h-72 overflow-y-auto",children:e.jsxs("table",{className:"w-full text-xs",children:[e.jsx("thead",{className:"text-muted-foreground",children:e.jsxs("tr",{children:[e.jsx("th",{className:"text-left font-normal py-1",children:"Kiedy (z godziną)"}),e.jsx("th",{className:"text-left font-normal",children:"Zdarzenie"}),e.jsx("th",{className:"text-left font-normal",children:"IP"})]})}),e.jsx("tbody",{children:k.events.map((z,H)=>e.jsxs("tr",{className:"border-t border-outline-variant/30",children:[e.jsx("td",{className:"py-1 tabular-nums whitespace-nowrap",children:Es(z.created_at)}),e.jsx("td",{children:fs(z.action)}),e.jsx("td",{className:"text-muted-foreground",children:z.ip??"—"})]},`${z.created_at}-${H}`))})]})})]})})})]},`${i.email}-${h}`)})})]})}),j&&e.jsxs("div",{className:"rounded-lg border border-outline-variant/40 bg-surface-variant/20 p-3 text-xs text-on-surface-variant space-y-1",children:[e.jsxs("p",{children:[e.jsx("b",{children:"Bez konta (automat / sprzed wdrożenia licznika):"}
16)," ",j.unattributed.calls.toLocaleString("pl-PL")," wywołań,"," ",A(j.unattributed.costUsd),". To crony (brief, skaner, portfele modelowe, potok bazy wiedzy) — nie da się ich przypisać do konta, bo żadnego za sobą nie mają."]}),j.deletedAccounts.calls>0&&e.jsxs("p",{children:[e.jsx("b",{children:"Konta już skasowane:"})," ",j.deletedAccounts.calls.toLocaleString("pl-PL")," wywołań,"," ",A(j.deletedAccounts.costUsd)," — ślad kosztu celowo przeżywa konto."]}),e.jsxs("p",{children:[e.jsx("b",{children:"Razem w oknie 30 dni:"})," ",A(j.totalCostUsd),"."]}),e.jsxs("p",{children:["Co dokładnie może odpalić zwykłe (nie-adminowe) konto i ile to kosztuje — patrz"," ",e.jsx("code",{children:"docs/KOSZTY_UZYTKOWNIKA.md"}),"."]}),e.jsxs("p",{children:[e.jsxs("b",{children:["Dzienny limit: ",A(re)," na konto"]})," (doba UTC, zeruje się o 1:00–2:00 w Polsce); konto właściciela jest bez limitu. Limit liczy TOKENY — poza nim zostają ElevenLabs (znaki), obrazy (za sztukę) i web search Anthropica (za wyszukiwanie). Nagrania lektora może uruchamiać wyłącznie właściciel; pozostali odsłuchują gotowe pliki."]})]}),r.isSuccess&&y.size>n.size&&e.jsx("p",{className:"text-xs text-on-surface-variant",children:"W dzienniku są zdarzenia z adresów spoza listy kont (nieudane rejestracje, konta skasowane) — tabela pokazuje tylko istniejące konta."})]})}function ea({email:s,spentToday:a}){if(Ls(s))return e.jsxs("span",{className:"text-muted-foreground",title:"Konto właściciela — bez limitu",children:[A(a)," · bez limitu"]});const u=Ts(a);return e.jsxs("span",{className:u.allowed?void 0:"text-error font-medium",title:u.message??"W budżecie",children:[A(a)," / ",A(re)]})}const ue={wysoki:{label:"koszt wysoki",cls:"bg-error/10 text-error border-error/30"},sredni:{label:"koszt średni",cls:"bg-amber-500/10 text-amber-700 dark:text-amber-400 border-amber-500/30"},niski:{label:"koszt niski",cls:"bg-green-500/10 text-green-700 dark:text-green-400 border-green-500/30"}},sa={anthropic:"Anthropic",openai:"OpenAI",google:"Google",elevenlabs:"ElevenLabs"};function aa(){const s=K(),{data:a,isLoading:p,error:u}=T({queryKey:["admin","models"],queryFn:rs,staleTime:3e4}),t=R({mutationFn:({key:y,model:j})=>is(y,j),onSuccess:(y,j)=>{C.success(j.model===null?"Przywrócono model domyślny — działa od następnego wywołania.":`Model zmieniony na ${j.model} — działa od następnego wywołania, bez deployu.`),s.invalidateQueries({queryKey:["admin","models"]})},onError:y=>C.error(y instanceof Error?y.message:"Nie udało się zapisać modelu.")});if(p)return e.jsx("p",{className:"text-sm text-on-surface-variant",children:"Ładowanie…"});if(u)return e.jsxs("p",{className:"text-sm text-error",children:["Nie udało się pobrać zestawienia: ",u instanceof Error?u.message:String(u)]});const r=(a==null?void 0:a.models)??[],c=new Map;for(const y of r)c.set(y.fn,[...c.get(y.fn)??[],y]);const o=r.filter(y=>y.overridden);return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"rounded-lg border border-outline-variant/40 bg-surface-variant/20 p-3 text-xs text-on-surface-variant space-y-1",children:[e.jsxs("p",{children:["Każde działanie AI ma model ",e.jsx("b",{children:"domyślny zapisany w kodzie"}),'. Zmiana tutaj zapisuje wyłącznie nadpisanie i działa od następnego wywołania — bez deployu. „Przywróć domyślny" zawsze wraca do wersji z kodu.']}),e.jsxs("p",{children:["Szukając kosztu patrz na ",e.jsx("b",{children:"częstotliwość"}),", nie na sam model: najdroższy jest tani model odpalony kilkaset razy. Licznik niżej zlicza każde wywołanie modelu w aplikacji per obszar i etap (poza obrazami Gemini i lektorem ElevenLabs, które nie rozliczają się w tokenach)."]}),o.length>0&&e.jsxs("p",{className:"text-on-surface",children:[e.jsxs("b",{children:["Nadpisane sloty (",o.length,"):"]})," ",o.map(y=>`${y.title} → ${y.current}`).join(" · ")]})]}),e.jsx(ta,{}),[...c.entries()].map(([y,j])=>e.jsxs("div",{className:"space-y-2",children:[e.jsx("h3",{className:"text-sm font-semibold font-mono text-on-surface-variant",children:y}),j.map(n=>{var l,d;return e.jsx("div",{className:"rounded-xl border border-outline-variant/40 p-3 space-y-2",children:e.jsxs("div",{className:"flex items-start justify-between gap-3 flex-wrap",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{className:"text-sm font-medium text-on-surface",children:n.title}),e.jsx("span",{className:`text-[10px] px-1.5 py-0.5 rounded border ${((l=ue[n.cost])==null?void 0:l.cls)??""}`,children:((d=ue[n.cost])==null?void 0:d.label)??n.cost}),e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded border border-outline-variant/50 text-on-surface-variant",children:sa[n.provider]??n.provider}),n.overridden&&e.jsxs("span",{className:"text-[10px] px-1.5 py-0.5 rounded border border-primary/40 bg-primary/10 text-primary",children:["zmieniony (domyślny: ",n.default,")"]})]}),e.jsx("p",{className:"text-xs text-on-surface-variant mt-1",children:n.description}),e.jsxs("p",{className:"text-xs text-on-surface-variant mt-0.5",children:[e.jsx("b",{children:"Jak często:"})," ",n.frequency]}),n.note&&e.jsxs("p",{className:"text-xs text-amber-700 dark:text-amber-400 mt-0.5",children:["⚠ ",n.note]})]}),e.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[e.jsxs(De,{value:n.current,onValueChange:m=>t.mutate({key:n.key,model:m===n.default?null:m}),disabled:t.isPending,children:[e.jsx(Ue,{className:"w-52 text-xs font-mono",children:e.jsx($e,{})}),e.jsx(Oe,{children:n.allowed.map(m=>e.jsxs(Fe,{value:m,className:"font-mono text-xs",children:[m,m===n.default?" (domyślny)":""]},m))})]}),n.overridden&&e.jsx($,{size:"sm",variant:"ghost",onClick:()=>t.mutate({key:n.key,model:null}),disabled:t.isPending,children:"Przywróć"})]})]})},n.key)})]},y))]})}function ta(){const[s,a]=L.useState(7),{data:p,isLoading:u,error:t}=T({queryKey:["admin","ai-usage"],queryFn:()=>os(30),staleTime:6e4}),r=p?hs(p.rows,s):null,c=r&&r.perDay.length>0?r.totalCostUsd/r.perDay.length:0;return e.jsxs("div",{className:"rounded-xl border border-outline-variant/40 p-3 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3 flex-wrap",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium text-on-surface",children:"Licznik kosztów AI — cała aplikacja"}),e.jsx("p",{className:"text-xs text-on-surface-variant mt-0.5",children:"Szacunek z cennika w kodzie (wsad = połowa ceny). Prawdą są tokeny; dokładny rachunek jest u dostawcy."})]}),e.jsx("div",{className:"flex items-center gap-1",children:[7,30].map(o=>e.jsxs($,{size:"sm",variant:s===o?"default":"ghost",onClick:()=>a(o),children:[o," dni"]},o))})]}),u&&e.jsx("p",{className:"text-sm text-on-surface-variant",children:"Ładowanie…"}),t&&e.jsxs("p",{className:"text-sm text-error",children:["Licznik niedostępny: ",t instanceof Error?t.message:String(t),/Unknown action/i.test(t instanceof Error?t.message:String(t))&&e.jsxs("span",{className:"block text-xs text-on-surface-variant mt-1",children:["Front jest nowy, a funkcja na serwerze stara — deploy frontu nie wdraża funkcji edge. Uruchom:",e.jsx("code",{className:"ml-1 font-mono",children:"supabase functions deploy admin-stats"})," (a po pierwszym wdrożeniu licznika także ",e.jsx("code",{className:"font-mono",children:"supabase db push"})," i deploy kb-import, kb-yt-watch, kb-ingest)."]})]}),r&&r.totalCalls===0&&e.jsx("p",{className:"text-sm text-on-surface-variant",children:"Brak wpisów w tym oknie. Licznik zapisuje każde wywołanie od wdrożenia — pierwsze słupki pojawią się po najbliższym ticku workera (import, destylator) albo publikacji dokumentu."}),r&&r.totalCalls>0&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"grid grid-cols-2 sm:grid-cols-4 gap-2 text-xs",children:[e.jsxs("div",{className:"rounded-lg bg-surface-variant/30 p-2",children:[e.jsxs("div",{className:"text-on-surface-variant",children:["Razem (",r.days," dni)"]}),e.jsx("div",{className:"text-base font-semibold text-on-surface",children:A(r.totalCostUsd)})]}),e.jsxs("div",{className:"rounded-lg bg-surface-variant/30 p-2",children:[e.jsx("div",{className:"text-on-surface-variant",children:"Średnio na dzień z danymi"}),e.jsx("div",{className:"text-base font-semibold text-on-surface",children:A(c)})]}),e.jsxs("div",{className:"rounded-lg bg-surface-variant/30 p-2",children:[e.jsx("div",{className:"text-on-surface-variant",children:"Wywołań"}),e.jsx("div",{className:"text-base font-semibold text-on-surface",children:r.totalCalls.toLocaleStr
16ing("pl-PL")})]}),e.jsxs("div",{className:"rounded-lg bg-surface-variant/30 p-2",children:[e.jsx("div",{className:"text-on-surface-variant",children:"Dni z danymi"}),e.jsxs("div",{className:"text-base font-semibold text-on-surface",children:[r.perDay.length,r.from&&r.to?` (${r.from} – ${r.to})`:""]})]})]}),r.unpricedCalls>0&&e.jsxs("p",{className:"text-xs text-amber-700 dark:text-amber-400",children:["⚠ ",r.unpricedCalls," wywołań bez ceny w cenniku (model spoza tabeli PRICES) — suma jest zaniżona."]}),e.jsx("div",{className:"flex flex-wrap gap-2",children:r.functions.map(o=>e.jsxs("div",{className:"rounded-lg border border-outline-variant/40 px-2.5 py-1.5 text-xs",children:[e.jsx("span",{className:"text-on-surface",children:be(o.fn)}),e.jsx("span",{className:"ml-2 font-semibold text-on-surface",children:A(o.costUsd)}),e.jsxs("span",{className:"ml-1 text-on-surface-variant",children:["(",Math.round(o.share*100),"%)"]})]},o.fn))}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs",children:[e.jsx("thead",{className:"text-on-surface-variant",children:e.jsxs("tr",{className:"border-b border-outline-variant/40",children:[e.jsx("th",{className:"text-left py-1 pr-2 font-medium",children:"Etap"}),e.jsx("th",{className:"text-left py-1 pr-2 font-medium",children:"Model"}),e.jsx("th",{className:"text-right py-1 pr-2 font-medium",children:"Koszt"}),e.jsx("th",{className:"text-right py-1 pr-2 font-medium",children:"Udział"}),e.jsx("th",{className:"text-right py-1 pr-2 font-medium",children:"Wywołań"}),e.jsx("th",{className:"text-right py-1 pr-2 font-medium",children:"Wsad"}),e.jsx("th",{className:"text-right py-1 pr-2 font-medium",children:"Wejście"}),e.jsx("th",{className:"text-right py-1 pr-2 font-medium",children:"Wyjście"}),e.jsx("th",{className:"text-right py-1 font-medium",children:"Cache"})]})}),e.jsx("tbody",{children:r.stages.map(o=>e.jsxs("tr",{className:"border-b border-outline-variant/20",children:[e.jsxs("td",{className:"py-1 pr-2 text-on-surface",children:[gs(o.fn,o.stage),e.jsxs("span",{className:"block font-mono text-[10px] text-on-surface-variant",children:[o.fn," · ",o.stage]})]}),e.jsx("td",{className:"py-1 pr-2 font-mono text-[11px] text-on-surface-variant",children:o.models.join(", ")}),e.jsx("td",{className:"py-1 pr-2 text-right font-semibold text-on-surface",children:A(o.costUsd)}),e.jsx("td",{className:"py-1 pr-2 text-right text-on-surface-variant",children:r.totalCostUsd>0?`${Math.round(o.costUsd/r.totalCostUsd*100)}%`:"—"}),e.jsx("td",{className:"py-1 pr-2 text-right text-on-surface-variant",children:o.calls.toLocaleString("pl-PL")}),e.jsx("td",{className:"py-1 pr-2 text-right text-on-surface-variant",children:o.calls>0?`${Math.round(o.batchCalls/o.calls*100)}%`:"—"}),e.jsx("td",{className:"py-1 pr-2 text-right text-on-surface-variant",children:(o.inputTokens+o.cacheReadTokens+o.cacheWriteTokens).toLocaleString("pl-PL")}),e.jsx("td",{className:"py-1 pr-2 text-right text-on-surface-variant",children:o.outputTokens.toLocaleString("pl-PL")}),e.jsx("td",{className:"py-1 text-right text-on-surface-variant",children:o.cacheShare===null?"—":`${Math.round(o.cacheShare*100)}%`})]},`${o.fn}/${o.stage}`))})]})}),e.jsxs("p",{className:"text-[11px] text-on-surface-variant",children:[e.jsx("b",{children:"Wsad"})," = udział wywołań przez Batch API (połowa ceny). ",e.jsx("b",{children:"Cache"})," = udział tokenów wejścia odczytanych z cache'u; zero przy stałym prompcie systemowym znaczy, że coś po cichu zmienia prefiks."]})]})]})}function na(){const s=K(),{data:a,isLoading:p,error:u}=T({queryKey:["admin","prompts"],queryFn:ts,staleTime:3e4}),[t,r]=L.useState(null),[c,o]=L.useState({}),y=R({mutationFn:({key:d,text:m})=>ns(d,m),onSuccess:(d,m)=>{C.success(m.text===null?"Przywrócono prompt domyślny.":"Zapisano nadpisanie promptu."),o(x=>{const{[m.key]:i,...h}=x;return h}),s.invalidateQueries({queryKey:["admin","prompts"]})},onError:d=>C.error(d instanceof Error?d.message:String(d))});if(p)return e.jsx("div",{className:"text-sm text-muted-foreground",children:"Ładowanie…"});if(u)return e.jsx(D,{error:u});const j=(a==null?void 0:a.prompts)??[],n=[];for(const d of j){let m=n.find(x=>x.fn===d.fn);m||(m={fn:d.fn,rows:[]},n.push(m)),m.rows.push(d)}const l=j.filter(d=>d.override!==null).length;return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"rounded-lg border border-border bg-surface-container-lowest p-4 text-sm text-muted-foreground",children:[e.jsxs("div",{className:"mb-1 flex items-center gap-2 font-medium text-foreground",children:[e.jsx(ae,{className:"h-4 w-4"})," Jak to działa"]}),"Domyślna wersja każdego promptu żyje w kodzie. Nadpisanie zapisane tutaj trafia do bazy i jest czytane przez funkcję przy ",e.jsx("b",{children:"każdym"}),' wywołaniu — zmiana działa od następnego użycia, bez deployu. „Przywróć domyślny" usuwa nadpisanie.',l>0&&e.jsxs(e.Fragment,{children:[" Obecnie nadpisane: ",e.jsx("b",{children:l}),"."]})]}),n.map(d=>e.jsxs("div",{children:[e.jsx("div",{className:"mb-2 text-xs font-semibold uppercase tracking-wide text-muted-foreground",children:d.fn}),e.jsx("ul",{className:"divide-y divide-border rounded-lg border border-border",children:d.rows.map(m=>{const x=t===m.key,i=m.override??m.defaultText,h=c[m.key]??i,f=h!==i;return e.jsxs("li",{className:"px-4 py-3",children:[e.jsxs("button",{type:"button",className:"flex w-full items-center justify-between gap-3 text-left",onClick:()=>r(x?null:m.key),children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"font-medium",children:m.title}),m.override!==null&&e.jsxs("span",{className:"rounded-full bg-amber-500/15 px-2 py-0.5 text-xs font-medium text-amber-700 dark:text-amber-400",children:["nadpisany",m.overrideUpdatedAt?` ${ie(m.overrideUpdatedAt)}`:""]}),!m.editable&&e.jsx("span",{className:"rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground",children:"dynamiczny — bez edycji"})]}),e.jsxs("div",{className:"mt-0.5 truncate text-xs text-muted-foreground",children:[e.jsx("code",{children:m.key})," · ",m.model]})]}),e.jsx("span",{className:"shrink-0 text-xs text-muted-foreground",children:x?"zwiń":"pokaż"})]}),x&&e.jsxs("div",{className:"mt-3 space-y-3",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:m.description}),m.editable?e.jsxs(e.Fragment,{children:[e.jsx(Ee,{value:h,onChange:k=>o(b=>({...b,[m.key]:k.target.value})),spellCheck:!1,className:"min-h-[280px] font-mono text-xs leading-relaxed"}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:["≈ ",ze(h).toLocaleStr
16ing("pl-PL")," tokenów (szacunek)",de(h)&&e.jsxs("span",{className:"block text-amber-700 dark:text-amber-400",children:["⚠ ",de(h)]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs($,{size:"sm",disabled:!f||y.isPending,onClick:()=>y.mutate({key:m.key,text:h}),children:[y.isPending?e.jsx(W,{className:"mr-1 h-3.5 w-3.5 animate-spin"}):e.jsx(ge,{className:"mr-1 h-3.5 w-3.5"}),"Zapisz nadpisanie"]}),m.override!==null&&e.jsxs($,{size:"sm",variant:"outline",disabled:y.isPending,onClick:()=>y.mutate({key:m.key,text:null}),children:[e.jsx(Ge,{className:"mr-1 h-3.5 w-3.5"})," Przywróć domyślny"]}),f&&e.jsx($,{size:"sm",variant:"ghost",onClick:()=>o(k=>{const{[m.key]:b,...S}=k;return S}),children:"Odrzuć zmiany"}),e.jsxs("span",{className:"ml-auto text-xs tabular-nums text-muted-foreground",children:[h.length.toLocaleString("pl-PL")," znaków",m.override!==null&&" · edytujesz nadpisanie"]})]})]}):e.jsx("div",{className:"rounded-md bg-muted/50 p-3 text-xs text-muted-foreground",children:"Ten prompt jest składany w locie z parametrów (format, dziedzina, liczba kategorii…), więc nie da się go podmienić jednym tekstem. Opis wskazuje plik w kodzie."})]})]},m.key)})})]},d.fn))]})}export{$a as default};

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.