PageSourceSearch

https://e0f.cx/assets/AdminCorpPage-o4bOPjUP.js

js e0f.cx collected 2026-09-24 14:59:37 UTC 150,584 bytes, 15 lines download raw bytes

1import{R as Qe,a as Re,r as n,U as Ve,V as He,j as e,G as i,e as ke,f as r,_ as v,a5 as es,d as Q,P as O,T as ue,ac as we,a3 as ss,Y as je,s as a,aJ as Z,l as f,a9 as de,aa as le,ah as Se,S as B,a2 as ne,ai as _,aY as Ce,ak as he,B as Ee,a1 as Ts,av as Ze,aZ as cs,C as ks,ab as p,$ as De,a6 as ie,ag as Je,ad as Ke,aA as Ps,bG as We,n as Bs,aM as er,aT as As,aG as sr,aX as rr,o as oe,a7 as ir,t as $e,aj as Pe,aV as ms,bj as _s,aK as ds,ax as Ae,I as Is,y as tr,aE as ar,aS as Es,bx as xe,b3 as is,aW as Os,aL as nr,b1 as lr,af as or,a8 as os,p as cr,aC as hs,aQ as Rs,Z as Vs,d5 as dr,g as hr,b$ as Us,w as Ms,q as mr,v as xr,bw as ur}from"./index-DJgzD7sm.js";import{g as ts,I as jr,c as pr}from"./countries-DSQaER6I.js";import{L as Ys}from"./LoadingOverlay-JipHUhRb.js";import{I as Ie}from"./IconBuilding-BvYo_SEj.js";import{I as Ds}from"./IconLanguage-B-qq73uU.js";import{I as gr}from"./IconMapPin-B_FR-DID.js";import{I as Gs}from"./IconDotsVertical-C9EwIjIC.js";import{I as Ye}from"./IconEdit-BBcyIY8S.js";import{I as Be}from"./IconTrash-Dw0tXwO_.js";import{T as Ls}from"./TagsInput-WAqJQINQ.js";import{N as ze}from"./NumberInput-37uLQK8S.js";import{S as Xe}from"./Switch-K_-dcS_2.js";import{S as Te}from"./Select-DYUJAPNs.js";import{I as ws}from"./IconShieldLock-B5lsNkxQ.js";import{I as bs}from"./IconEye-q7UJ_CdM.js";import{I as vs}from"./IconPlayerPlay-C36Bx94L.js";import{P as xs}from"./Pagination-DRIoAR3s.js";import{C as fr}from"./Code-Bus1hUjD.js";import{I as wr}from"./IconCurrencyRubel-DPVJcMlG.js";import{S as ys}from"./SegmentedControl-C3Jsnrqb.js";import{I as zs}from"./IconShieldOff-DmvaaJl6.js";import{I as br}from"./IconCode-cPKZCG_s.js";import{I as Ss}from"./IconDeviceFloppy-DuwOmVUa.js";import{I as us}from"./IconPlugConnected-FEBWBG0T.js";import{I as vr}from"./IconTerminal2-t9Wvlkfj.js";import{I as $s}from"./IconHistory-D0pbdr_i.js";import{D as Ws}from"./DatePickerInput-j4XksW4M.js";import{I as yr}from"./IconFilter-DiM4m2B8.js";import{I as zr}from"./IconBuildingBank-D8-DNk_M.js";import{I as Js}from"./IconExternalLink-PMgE6Ft5.js";import{I as Ks}from"./IconFileText-xJxAW6Wx.js";import{M as Sr}from"./MultiSelect-hVAuG819.js";import{u as Cr}from"./use-debounced-value-DCqVxYTT.js";import{I as Tr}from"./IconSearch-BtX1OOjH.js";import{I as Zs}from"./IconLink-B9kbLjXb.js";import{I as kr}from"./IconReload-DdvPCfnl.js";import"./PillsInput-Cg2GezZK.js";import"./react-number-format.es-hx5beCWS.js";import"./clamp-DTmYCdls.js";import"./DatePicker-c2hYuHtE.js";import"./pick-calendar-levels-props-ns0wLwTs.js";const Pr=[["path",{d:"M14 3v4a1 1 0 0 0 1 1h4",key:"svg-0"}],["path",{d:"M5 8v-3a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2h-5",key:"svg-1"}],["path",{d:"M6 14m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0",key:"svg-2"}],["path",{d:"M4.5 17l-1.5 5l3 -1.5l3 1.5l-1.5 -5",key:"svg-3"}]],Ns=Qe("outline","file-certificate","FileCertificate",Pr);const Ar=[["path",{d:"M14 3v4a1 1 0 0 0 1 1h4",key:"svg-0"}],["path",{d:"M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z",key:"svg-1"}],["path",{d:"M9 7l1 0",key:"svg-2"}],["path",{d:"M9 13l6 0",key:"svg-3"}],["path",{d:"M13 17l2 0",key:"svg-4"}]],Xs=Qe("outline","file-invoice","FileInvoice",Ar);const Ir=[["path",{d:"M14 3v4a1 1 0 0 0 1 1h4",key:"svg-0"}],["path",{d:"M5 12v-7a2 2 0 0 1 2 -2h7l5 5v4",key:"svg-1"}],["path",{d:"M5 18h1.5a1.5 1.5 0 0 0 0 -3h-1.5v6",key:"svg-2"}],["path",{d:"M17 18h2",key:"svg-3"}],["path",{d:"M20 15h-3v6",key:"svg-4"}],["path",{d:"M11 15v6h1a2 2 0 0 0 2 -2v-2a2 2 0 0 0 -2 -2h-1z",key:"svg-5"}]],Er=Qe("outline","file-type-pdf","FileTypePdf",Ir);const $r=[["path",{d:"M15 8h.01",key:"svg-0"}],["path",{d:"M12.5 21h-6.5a3 3 0 0 1 -3 -3v-12a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v6.5",key:"svg-1"}],["path",{d:"M3 16l5 -5c.928 -.893 2.072 -.893 3 0l3.5 3.5",key:"svg-2"}],["path",{d:"M14 14l1 -1c.679 -.653 1.473 -.829 2.214 -.526",key:"svg-3"}],["path",{d:"M19 22v-6",key:"svg-4"}],["path",{d:"M22 19l-3 -3l-3 3",key:"svg-5"}]],Fs=Qe("outline","photo-up","PhotoUp",$r);const Br=[["path",{d:"M20 16l-4 4",key:"svg-0"}],["path",{d:"M7 12l5 5l-1.5 1.5a3.536 3.536 0 1 1 -5 -5l1.5 -1.5z",key:"svg-1"}],["path",{d:"M17 12l-5 -5l1.5 -1.5a3.536 3.536 0 1 1 5 5l-1.5 1.5z",key:"svg-2"}],["path",{d:"M3 21l2.5 -2.5",key:"svg-3"}],["path",{d:"M18.5 5.5l2.5 -2.5",key:"svg-4"}],["path",{d:"M10 11l-2 2",key:"svg-5"}],["path",{d:"M13 14l-2 2",key:"svg-6"}],["path",{d:"M16 16l4 4",key:"svg-7"}]],Or=Qe("outline","plug-connected-x","PlugConnectedX",Br),Cs={RU:"🇷🇺",DE:"🇩🇪",NL:"🇳🇱",US:"🇺🇸",GB:"🇬🇧",FR:"🇫🇷",AU:"🇦🇺",AT:"🇦🇹",AL:"🇦🇱",AR:"🇦🇷",AM:"🇦🇲",BY:"🇧🇾",BE:"🇧🇪",BG:"🇧🇬",BR:"🇧🇷",HU:"🇭🇺",HK:"🇭🇰",GR:"🇬🇷",DK:"🇩🇰",IL:"🇮🇱",IN:"🇮🇳",ID:"🇮🇩",IE:"🇮🇪",IS:"🇮🇸",ES:"🇪🇸",IT:"🇮🇹",KZ:"🇰🇿",CA:"🇨🇦",CY:"🇨🇾",LV:"🇱🇻",LT:"🇱🇹",LU:"🇱🇺",MY:"🇲🇾",MX:"🇲🇽",MD:"🇲🇩",NO:"🇳🇴",NZ:"🇳🇿",PL:"🇵🇱",PT:"🇵🇹",RO:"🇷🇴",RS:"🇷🇸",SG:"🇸🇬",SK:"🇸🇰",SI:"🇸🇮",TH:"🇹🇭",TR:"🇹🇷",UA:"🇺🇦",FI:"🇫🇮",HR:"🇭🇷",CZ:"🇨🇿",CH:"🇨🇭",SE:"🇸🇪",EE:"🇪🇪",ZA:"🇿🇦",KR:"🇰
1🇷",JP:"🇯🇵",TW:"🇹🇼",AE:"🇦🇪",VN:"🇻🇳",PH:"🇵🇭"};function Rr({embedded:c=!1}){const{token:k}=Re(),[N,$]=n.useState(!1),[F,g]=n.useState([]),[D,h]=n.useState(null),[d,{open:u,close:S}]=Ve(!1),[A,z]=n.useState(!1),[T,M]=n.useState([]),[q,C]=n.useState(!1),[H,U]=n.useState([]),x=He({initialValues:{name:"",description:"",nameEn:"",descriptionEn:"",featuresEn:[],maxUsers:10,trafficLimit:0,maxDevicesPerMember:5,maxLocations:0,price:0,period:30,features:[],availableServers:[],extraProtocolsEnabled:!1,protocolPricing:[],isActive:!0,sortOrder:0}}),E=n.useCallback(async()=>{if(k){C(!0);try{const s=await fetch("/api/servers/locations",{headers:{Authorization:`Bearer ${k}`}});if(s.ok){const o=await s.json();M(o)}}catch(s){console.error("Failed to load locations:",s)}finally{C(!1)}}},[k]);n.useEffect(()=>{y(),E()},[E]);const y=async()=>{$(!0);try{const s=await fetch("/api/admin/corporate/plans",{headers:{Authorization:`Bearer ${k}`}});s.ok&&g(await s.json())}catch(s){console.error("Failed to load plans:",s)}finally{$(!1)}},K=()=>{z(!1),h(null),x.reset(),U([]),u()},w=s=>{z(!0),h(s),x.setValues({name:s.name,description:s.description||"",nameEn:s.nameEn||"",descriptionEn:s.descriptionEn||"",featuresEn:s.featuresEn||[],maxUsers:s.maxUsers,trafficLimit:s.trafficLimit?s.trafficLimit/(1024*1024*1024):0,maxDevicesPerMember:s.maxDevicesPerMember||5,maxLocations:s.maxLocations??0,price:s.price/100,period:s.period,features:s.features||[],availableServers:s.availableServers||[],extraProtocolsEnabled:s.extraProtocolsEnabled??!1,protocolPricing:s.protocolPricing||[],isActive:s.isActive,sortOrder:s.sortOrder}),U(s.availableServers||[]),u()},ee=s=>{U(o=>o.includes(s)?o.filter(P=>P!==s):[...o,s])},V=()=>{U(T.map(s=>s.countryCode))},L=()=>{U([])},be=async s=>{try{const o={name:s.name,description:s.description||null,nameEn:s.nameEn?.trim()||null,descriptionEn:s.descriptionEn?.trim()||null,featuresEn:s.featuresEn&&s.featuresEn.length>0?s.featuresEn:null,maxUsers:s.maxUsers,trafficLimit:s.trafficLimit?s.trafficLimit*1024*1024*1024:null,maxDevicesPerMember:s.maxDevicesPerMember,maxLocations:s.maxLocations||0,price:Math.round(s.price*100),period:s.period,features:s.features,availableServers:H.length>0?H:null,extraProtocolsEnabled:s.extraProtocolsEnabled,protocolPricing:s.extraProtocolsEnabled?(s.protocolPricing||[]).filter(X=>X.protocol&&X.countryCode&&X.price>=0).map(X=>({protocol:X.protocol,countryCode:X.countryCode.toUpperCase(),price:Math.round(X.price)})):null,isActive:s.isActive,sortOrder:s.sortOrder},P=A?`/api/admin/corporate/plans/${D?.id}`:"/api/admin/corporate/plans",G=await fetch(P,{method:A?"PATCH":"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${k}`},body:JSON.stringify(o)});if(G.ok)p.show({title:A?"План обновлён":"План создан",message:`${s.name}`,color:"green",icon:e.jsx(we,{size:16})}),S(),y();else{const X=await G.json();throw new Error(X.message)}}catch(o){p.show({title:"Ошибка",message:o.message||"Не удалось сохранить план",color:"red"})}},ve=async s=>{if(confirm(`Удалить план "${s.name}"?`))try{const o=await fetch(`/api/admin/corporate/plans/${s.id}`,{method:"DELETE",headers:{Authorization:`Bearer ${k}`}});if(o.ok)p.show({title:"План удалён",message:s.name,color:"green"}),y();else{const P=await o.json();throw new Error(P.message)}}catch(o){p.show({title:"Ошибка",message:o.message||"Не удалось удалить план",color:"red"})}},ce=s=>(s/100).toLocaleString("ru-RU")+" ₽",Y=s=>s?`${s/(1024*1024*1024)} GB`:"Безлимит",re=e.jsxs(e.Fragment,{children:[e.jsx(Ys,{visible:N}),e.jsxs(i,{justify:"space-between",mb:"xl",children:[!c&&e.jsxs("div",{children:[e.jsx(ke,{order:2,children:"Корпоративные планы"}),e.jsx(r,{c:"dimmed",children:"Управление тарифами для корпоративных клиентов"})]}),e.jsx(v,{leftSection:e.jsx(es,{size:16}),onClick:K,ml:c?"auto":void 0,children:"Создать план"})]}),e.jsxs(Q,{cols:{base:1,sm:3},mb:"xl",children:[e.jsx(O,{p:"md",radius:"md",withBorder:!0,children:e.jsxs(i,{children:[e.jsx(ue,{size:"lg",radiu
1s:"md",variant:"light",color:"blue",children:e.jsx(Ie,{size:20})}),e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Всего планов"}),e.jsx(r,{size:"xl",fw:700,children:F.length})]})]})}),e.jsx(O,{p:"md",radius:"md",withBorder:!0,children:e.jsxs(i,{children:[e.jsx(ue,{size:"lg",radius:"md",variant:"light",color:"green",children:e.jsx(we,{size:20})}),e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Активных"}),e.jsx(r,{size:"xl",fw:700,children:F.filter(s=>s.isActive).length})]})]})}),e.jsx(O,{p:"md",radius:"md",withBorder:!0,children:e.jsxs(i,{children:[e.jsx(ue,{size:"lg",radius:"md",variant:"light",color:"violet",children:e.jsx(ss,{size:20})}),e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Макс. пользователей"}),e.jsx(r,{size:"xl",fw:700,children:Math.max(...F.map(s=>s.maxUsers),0)})]})]})})]}),e.jsx(je,{withBorder:!0,children:e.jsxs(a,{striped:!0,highlightOnHover:!0,children:[e.jsx(a.Thead,{children:e.jsxs(a.Tr,{children:[e.jsx(a.Th,{children:"Название"}),e.jsx(a.Th,{children:"Сотрудников"}),e.jsx(a.Th,{children:"Трафик"}),e.jsx(a.Th,{children:"Локации"}),e.jsx(a.Th,{children:"Цена"}),e.jsx(a.Th,{children:"Период"}),e.jsx(a.Th,{children:"Статус"}),e.jsx(a.Th,{children:"Действия"})]})}),e.jsxs(a.Tbody,{children:[F.map(s=>e.jsxs(a.Tr,{children:[e.jsxs(a.Td,{children:[e.jsxs(i,{gap:6,wrap:"nowrap",children:[e.jsx(r,{fw:500,children:s.name}),(s.nameEn||s.descriptionEn||s.featuresEn&&s.featuresEn.length>0)&&e.jsx(Z,{label:s.nameEn?`EN: ${s.nameEn}`:"Есть английские переводы (описание / преимущества)",multiline:!0,w:240,children:e.jsx(f,{variant:"light",color:"indigo",size:"xs",leftSection:e.jsx(Ds,{size:10}),children:"EN"})})]}),s.description&&e.jsx(r,{size:"xs",c:"dimmed",lineClamp:1,children:s.description})]}),e.jsxs(a.Td,{children:["до ",s.maxUsers]}),e.jsx(a.Td,{children:Y(s.trafficLimit)}),e.jsx(a.Td,{children:s.availableServers&&s.availableServers.length>0?e.jsx(Z,{label:s.availableServers.map(o=>{const P=T.find(G=>G.countryCode===o);return P?`${Cs[o]||"🌍"} ${P.country}`:o}).join(", "),multiline:!0,w:200,children:e.jsxs(f,{variant:"light",color:"blue",leftSection:e.jsx(gr,{size:12}),children:[s.availableServers.length," стран"]})}):e.jsx(f,{variant:"light",color:"green",children:"Все серверы"})}),e.jsx(a.Td,{fw:500,children:ce(s.price)}),e.jsxs(a.Td,{children:[s.period," дней"]}),e.jsx(a.Td,{children:e.jsx(f,{color:s.isActive?"green":"gray",children:s.isActive?"Активен":"Отключён"})}),e.jsx(a.Td,{children:e.jsxs(de,{position:"bottom-end",children:[e.jsx(de.Target,{children:e.jsx(le,{variant:"subtle",children:e.jsx(Gs,{size:16})})}),e.jsxs(de.Dropdown,{children:[e.jsx(de.Item,{leftSection:e.jsx(Ye,{size:14}),onClick:()=>w(s),children:"Редактировать"}),e.jsx(de.Item,{leftSection:e.jsx(Be,{size:14}),color:"red",onClick:()=>ve(s),children:"Удалить"})]})]})})]},s.id)),F.length===0&&e.jsx(a.Tr,{children:e.jsx(a.Td,{colSpan:8,children:e.jsx(r,{ta:"center",c:"dimmed",py:"xl",children:"Нет корпоративных планов"})})})]})]})}),e.jsx(Se,{opened:d,onClose:S,title:A?"Редактировать план":"Создать план",size:"lg",children:e.jsx("form",{onSubmit:x.onSubmit(be),children:e.jsxs(B,{children:[e.jsxs(ne,{defaultValue:"ru",variant:"outline",radius:"md",children:[e.jsxs(ne.List,{children:[e.jsx(ne.Tab,{value:"ru",children:"Русский"}),e.jsx(ne.Tab,{value:"en",leftSection:e.jsx(Ds,{size:14}),children:"English"})]}),e.jsx(ne.Panel,{value:"ru",pt:"md",children:e.jsxs(B,{gap:"sm",children:[e.jsx(_,{label:"Название",placeholder:"Бизнес",required:!0,...x.getInputProps("name")}),e.jsx(Ce,{label:"Описание",placeholder:"Описание плана...",autosize:!0,minRows:2,...x.getInputProps("description")}),e.jsx(Ls,{label:"Преимущества",placeholder:"Введите и нажмите Enter",...x.getInputProps("features")})]})}),e.jsx(ne.Panel,{value:"en",pt:"md",children:e.jsxs(B,{gap:"sm",children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Оставьте поля пустыми, чтобы английская версия использовала русский текст как fallback."}),e.jsx(_,{label:"Name (EN)",placeholder:"Business",...x.getInputProps("nameEn")}),e.jsx(Ce,{label:"Description (EN)",placeholder:"Plan description...",autosize:!0,minRows:2,...x.getInputProps("descriptionEn")}),e.jsx(Ls,{label:"Features (EN)",placeholder:"Type and press Enter",...x.getInputProps("featuresEn")})]})})]}),e.jsxs(Q,{cols:2,children:[e.jsx(ze,{label:"Макс. сотрудников",min:1,required:!0,...x.getInputProps("maxUsers")}),e.jsx(ze,{label:"Лимит трафика (GB)",description:"0 = безлимит",min:0,...x.getInputProps("trafficLim
1it")})]}),e.jsxs(Q,{cols:2,children:[e.jsx(ze,{label:"Устройств на сотрудника",description:"Максимум устройств для каждого сотрудника",min:1,max:100,required:!0,...x.getInputProps("maxDevicesPerMember")}),e.jsx(ze,{label:"Лимит локаций при покупке",description:"0 = без ограничения. > 0 — клиент видит все локации, но выберет не более N",min:0,max:500,...x.getInputProps("maxLocations")})]}),e.jsxs(Q,{cols:2,children:[e.jsx(ze,{label:"Цена (₽)",min:0,required:!0,...x.getInputProps("price")}),e.jsx(ze,{label:"Период (дней)",min:1,required:!0,...x.getInputProps("period")})]}),e.jsx(he,{label:"Доступные локации",labelPosition:"center"}),e.jsxs(Ee,{children:[e.jsxs(i,{justify:"space-between",mb:"xs",children:[e.jsxs(i,{gap:"xs",children:[e.jsx(ue,{size:"sm",variant:"light",color:"blue",children:e.jsx(Ts,{size:14})}),e.jsxs(r,{size:"sm",fw:500,children:["Выбрано: ",H.length," из ",T.length]})]}),e.jsxs(i,{gap:"xs",children:[e.jsx(v,{size:"xs",variant:"light",onClick:V,children:"Выбрать все"}),e.jsx(v,{size:"xs",variant:"subtle",color:"gray",onClick:L,children:"Очистить"})]})]}),e.jsx(r,{size:"xs",c:"dimmed",mb:"sm",children:"Пустой выбор = доступ ко всем серверам"}),e.jsx(Ze,{h:200,offsetScrollbars:!0,children:e.jsx(Q,{cols:3,spacing:"xs",children:T.map(s=>{const o=H.includes(s.countryCode);return e.jsx(O,{p:"xs",radius:"md",withBorder:!0,style:{cursor:"pointer",borderColor:o?"var(--mantine-color-blue-5)":void 0,background:o?"rgba(34, 139, 230, 0.1)":void 0},onClick:()=>ee(s.countryCode),children:e.jsxs(i,{gap:"xs",wrap:"nowrap",children:[e.jsx(cs,{countryCode:s.countryCode,flagEmoji:Cs[s.countryCode]||s.flag||"🌍",size:24}),e.jsxs(Ee,{style:{flex:1,minWidth:0},children:[e.jsx(r,{size:"xs",fw:500,truncate:!0,children:s.country}),e.jsxs(r,{size:"xs",c:"dimmed",children:[s.onlineCount," ON"]})]}),o&&e.jsx(ue,{size:"xs",color:"blue",variant:"filled",radius:"xl",children:e.jsx(we,{size:10})})]})},s.countryCode)})})})]}),e.jsx(he,{label:"Дополнительные протоколы",labelPosition:"center"}),e.jsx(Xe,{label:"Разрешить выбор доп. протоколов в этом плане",description:"WireGuard / AmneziaWG. Цены добавляются к стоимости заказа.",...x.getInputProps("extraProtocolsEnabled",{type:"checkbox"})}),x.values.extraProtocolsEnabled&&e.jsx(Ur,{value:x.values.protocolPricing,onChange:s=>x.setFieldValue("protocolPricing",s),availableLocations:H,allLocations:T}),e.jsxs(Q,{cols:2,children:[e.jsx(ze,{label:"Порядок сортировки",...x.getInputProps("sortOrder")}),e.jsx(Xe,{label:"Активен",mt:"xl",...x.getInputProps("isActive",{type:"checkbox"})})]}),e.jsxs(i,{justify:"flex-end",mt:"md",children:[e.jsx(v,{variant:"subtle",onClick:S,children:"Отмена"}),e.jsx(v,{type:"submit",children:A?"Сохранить":"Создать"})]})]})})})]});return c?re:e.jsx(ks,{size:"xl",py:"xl",children:re})}function Ur({value:c,onChange:k,availableLocations:N,allLocations:$}){const F=(N.length>0?$.filter(u=>N.includes(u.countryCode)):$).map(u=>({value:u.countryCode,label:`${Cs[u.countryCode]||u.flag||"🌍"} ${u.country} (${u.countryCode})`})),g=[{value:"wireguard",label:"WireGuard"},{value:"amneziawg",label:"AmneziaWG"}],D=(u,S)=>{k(c.map((A,z)=>z===u?{...A,...S}:A))},h=u=>{k(c.filter((S,A)=>A!==u))},d=()=>{k([...c,{protocol:"wireguard",countryCode:F[0]?.value||"",price:0}])};return e.jsx(je,{withBorder:!0,p:"md",children:e.jsxs(B,{gap:"sm",children:[e.jsxs(i,{justify:"space-between",children:[e.jsx(r,{size:"sm",fw:500,children:"Прайс-матрица: цена за пару (протокол × страна)"}),e.jsx(v,{size:"xs",variant:"light",leftSection:e.jsx(es,{size:14}),onClick:d,children:"Добавить"})]}),c.length===0?e.jsx(r,{size:"xs",c:"dimmed",children:"Нет записей. Добавьте хотя бы одну пару, иначе клиент не сможет выбрать доп. протоколы."}):e.jsx(B,{gap:"xs",children:c.map((u,S)=>e.jsxs(i,{gap:"xs",align:"flex-end",wrap:"nowrap",children:[e.jsx(Te,{label:"Протокол",size:"xs",data:g,value:u.protocol,onCh
1ange:A=>D(S,{protocol:A||"wireguard"}),style:{minWidth:140}}),e.jsx(Te,{label:"Страна",size:"xs",searchable:!0,data:F,value:u.countryCode,onChange:A=>D(S,{countryCode:A||""}),style:{flex:1,minWidth:200}}),e.jsx(ze,{label:"Цена (₽)",description:"за период плана",size:"xs",min:0,value:Math.round((u.price||0)/100),onChange:A=>D(S,{price:Math.max(0,Math.round(Number(A||0)*100))}),style:{width:130}}),e.jsx(le,{color:"red",variant:"subtle",size:"lg",onClick:()=>h(S),children:e.jsx(Be,{size:16})})]},S))})]})})}const Mr={wireguard:"WireGuard",amneziawg:"AmneziaWG"};function js(c){return Mr[c?.toLowerCase()]||c||"—"}const Ge={pending_payment:{color:"yellow",label:"Ожидает оплаты"},paid:{color:"blue",label:"Оплачен"},in_progress:{color:"cyan",label:"Настраивается"},active:{color:"green",label:"Активен"},suspended:{color:"orange",label:"Приостановлен"},cancelled:{color:"red",label:"Отменён"}};function Dr({embedded:c=!1}){const{token:k}=Re(),[N,$]=n.useState(!1),[F,g]=n.useState([]),[D,h]=n.useState(null),[d,u]=n.useState(null),[S,A]=n.useState(null),[z,T]=n.useState(1),[M,q]=n.useState(1),[C,{open:H,close:U}]=Ve(!1),[x,{open:E,close:y}]=Ve(!1),[K,{open:w,close:ee}]=Ve(!1),[V,L]=n.useState(null),[be,ve]=n.useState(!1),[ce,Y]=n.useState(!1),[re,s]=n.useState(!1),[o,P]=n.useState([]),G=He({initialValues:{email:"",newPassword:""},validate:{email:l=>l?/^\S+@\S+$/.test(l)?null:"Некорректный email":"Email обязателен",newPassword:l=>l&&l.length<6?"Минимум 6 символов":null}}),X=He({initialValues:{squadName:"",adminNotes:""}});n.useEffect(()=>{pe()},[z,S]),n.useEffect(()=>{Ne()},[]);const Ne=async()=>{try{const l=await fetch("/api/admin/corporate/remnawave/squads",{headers:{Authorization:`Bearer ${k}`}});l.ok&&P(await l.json())}catch(l){console.error("Failed to load Remnawave squads:",l)}},pe=async()=>{$(!0);try{const l=new URLSearchParams;l.set("page",z.toString()),l.set("limit","20"),S&&l.set("status",S);const[I,se]=await Promise.all([fetch(`/api/admin/corporate/orders?${l.toString()}`,{headers:{Authorization:`Bearer ${k}`}}),fetch("/api/admin/corporate/stats",{headers:{Authorization:`Bearer ${k}`}})]);if(I.ok){const Ue=await I.json();g(Ue.orders),q(Ue.totalPages)}se.ok&&h(await se.json())}catch(l){console.error("Failed to load orders:",l)}finally{$(!1)}},m=async l=>{try{const I=await fetch(`/api/admin/corporate/orders/${l.id}`,{headers:{Authorization:`Bearer ${k}`}});I.ok&&(u(await I.json()),H())}catch(I){console.error("Failed to load order details:",I)}},W=l=>{u(l),X.setValues({squadName:l.companyName.toLowerCase().replace(/[^a-z0-9]/g,"_").substring(0,20),adminNotes:l.adminNotes||""}),E()},te=async l=>{if(d)try{const I=await fetch(`/api/admin/corporate/orders/${d.id}/activate`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${k}`},body:JSON.stringify(l)});if(I.ok)p.show({title:"Заказ активирован",message:`Организация "${d.companyName}" создана`,color:"green",icon:e.jsx(we,{size:16})}),y(),pe();else{const se=await I.json();throw new Error(se.message)}}catch(I){p.show({title:"Ошибка",message:I.message||"Не удалось активировать заказ",color:"red"})}},ge=async(l,I)=>{try{(await fetch(`/api/admin/corporate/orders/${l}`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${k}`},body:JSON.stringify({status:I})})).ok&&(p.show({title:"Статус обновлён",message:Ge[I]?.label||I,color:"green"}),pe())}catch(se){console.error("Failed to update status:",se)}},Le=async l=>{try{const I=await fetch(`/api/admin/corporate/orders/${l}/verify-payment`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${k}`}}),se=await I.json().catch(()=>({}));I.ok&&se?.confirmed?(p.show({title:"Оплата подтверждена",message:"Заказ помечен оплаченным",color:"green"}),pe()):I.ok?p.show({title:"Оплата не найдена",message:`Статус в Т-Банке: ${se?.providerStatus||"не оплачен"}`,color:"yellow"}):p.show({title:"Ошибка проверки",message:se?.message||"Не удалось проверить оплату",color:"red"})}catch(I){console.error("Failed to verify payment:",I),p.show({title:"Ошибка",message:"Сбой запроса",color:"red"})}},Oe=l=>{L(l),w()},fe=async()=>
1{if(V){ve(!0);try{const l=await fetch(`/api/admin/corporate/orders/${V.id}`,{method:"DELETE",headers:{Authorization:`Bearer ${k}`}});if(l.ok)p.show({title:"Заказ удалён",message:`Заказ #${V.id} (${V.companyName}) удалён`,color:"green",icon:e.jsx(we,{size:16})}),ee(),L(null),pe();else{const I=await l.json().catch(()=>({}));throw new Error(I.message||"Не удалось удалить заказ")}}catch(l){p.show({title:"Ошибка",message:l.message||"Не удалось удалить заказ",color:"red"})}finally{ve(!1)}}},Fe=()=>{d?.organization&&(G.setValues({email:d.organization.ownerEmail||d.contactEmail,newPassword:""}),Y(!0))},t=async l=>{if(d?.organization){s(!0);try{const I=await fetch(`/api/admin/corporate/organizations/${d.organization.id}/credentials`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${k}`},body:JSON.stringify({email:l.email,password:l.newPassword||void 0})});if(I.ok)p.show({title:"Данные обновлены",message:l.newPassword?"Email и пароль изменены":"Email изменён",color:"green",icon:e.jsx(we,{size:16})}),Y(!1),m(d);else{const se=await I.json();throw new Error(se.message)}}catch(I){p.show({title:"Ошибка",message:I.message||"Не удалось обновить данные",color:"red"})}finally{s(!1)}}},j=l=>(l/100).toLocaleString("ru-RU")+" ₽",R=l=>oe(l).format("DD.MM.YYYY HH:mm"),ye=e.jsxs(e.Fragment,{children:[e.jsx(Ys,{visible:N}),e.jsxs(i,{justify:"space-between",mb:"xl",children:[!c&&e.jsxs("div",{children:[e.jsx(ke,{order:2,children:"Корпоративные заказы"}),e.jsx(r,{c:"dimmed",children:"Управление заказами корпоративных клиентов"})]}),e.jsx(v,{leftSection:e.jsx(De,{size:16}),variant:"light",onClick:pe,ml:c?"auto":void 0,children:"Обновить"})]}),D&&e.jsxs(Q,{cols:{base:2,sm:3,md:6},mb:"xl",children:[e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Всего заказов"}),e.jsx(r,{size:"xl",fw:700,children:D.totalOrders})]}),e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Ожидают оплаты"}),e.jsx(r,{size:"xl",fw:700,c:"yellow",children:D.pendingOrders})]}),e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Оплачены"}),e.jsx(r,{size:"xl",fw:700,c:"blue",children:D.paidOrders})]}),e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Активны"}),e.jsx(r,{size:"xl",fw:700,c:"green",children:D.activeOrders})]}),e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Организаций"}),e.jsx(r,{size:"xl",fw:700,children:D.totalOrganizations})]}),e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Сотрудников"}),e.jsx(r,{size:"xl",fw:700,children:D.totalMembers})]})]}),e.jsx(je,{withBorder:!0,mb:"md",children:e.jsx(i,{children:e.jsx(Te,{placeholder:"Все статусы",clearable:!0,value:S,onChange:A,data:Object.entries(Ge).map(([l,{label:I}])=>({value:l,label:I})),style:{width:200}})})}),e.jsxs(je,{withBorder:!0,children:[e.jsxs(a,{striped:!0,highlightOnHover:!0,children:[e.jsx(a.Thead,{children:e.jsxs(a.Tr,{children:[e.jsx(a.Th,{children:"ID"}),e.jsx(a.Th,{children:"Компания"}),e.jsx(a.Th,{children:"Контакт"}),e.jsx(a.Th,{children:"План"}),e.jsx(a.Th,{children:"Сумма"}),e.jsx(a.Th,{children:"Статус"}),e.jsx(a.Th,{children:"Дата"}),e.jsx(a.Th,{children:"Действия"})]})}),e.jsxs(a.Tbody,{children:[F.map(l=>{const I=l.kind==="protocol_addon",se=!I&&!!l.targetOrganization,Ue=Array.isArray(l.selectedProtocols)?l.selectedProtocols:[];return e.jsxs(a.Tr,{children:[e.jsx(a.Td,{children:e.jsxs(r,{size:"sm",c:"dimmed",children:["#",l.id]})}),e.jsx(a.Td,{children:e.jsx(i,{gap:6,wrap:"nowrap",align:"flex-start",children:e.jsxs("div",{style:{minWidth:0},children:[e.jsx(r,{fw:500,truncate:!0,children:I&&l.targetOrganization?.name||l.companyName}),I?e.jsx(f,{mt:4,size:"xs",variant:"light",color:"violet",leftSection:e.jsx(ws,{size:10}),children:"Докупка протокола"}):se?e.jsx(f,{mt:4,size:"xs",variant:"light",color:"teal",leftSection:e.jsx(De,{size:10}),children:"Продление"}):l.inn&&e.jsxs(r,{size:"xs",c:"dimmed",children:["ИНН: ",l.inn]})]})})}),e.jsxs(a.Td,{children:[e.jsx(r,{size:"sm",children:l.contactName}),e.jsx(r,{size:"xs",c:"dimmed",children:l.contactEmail})]}),e.jsx(a.Td,{children:I?e.jsxs(B,{gap:4,children:[e.jsx(r,{size:"sm",fw:500,children:"Доп. протоколы"}),e.jsx(i,{gap:4,wrap:"wrap",children:Ue.length>0?Ue.map((Me,b)=>e.jsxs(f,{size:"xs",variant:"light",color:"violet",children:[js(Me.protocol)," · ",ts(Me.countryCode,"ru")]},`${Me.protocol}-${Me.countryCode}-${b}`)):e.jsx(r,{size:"xs",c:"dimmed",children:"—"})})]}):e.jsxs(B,{gap:2,children:[e.jsx(r,{size:"sm",children:l.plan.name}),e.jsxs(r,{size:"xs",c:"dimmed",children:[l.requestedUsers," сотр."]}),Ue.length>0&&e.jsx(i,{gap:4,wrap:"wrap",mt:4,children:Ue.map((Me,b)=>e.jsxs(f,{size:"xs",variant:"dot",color:"violet",leftSection:e.jsx(es,{size:8}),children:[js(Me.protocol)," · ",ts(Me.countryCode,"ru")]},`${Me.protocol}-${Me.countryCode}-${b}`))})]})}),e.jsx(a.Td,{fw:500,children:j(l.amount)}),e.jsx(a.Td,{children:e.jsx(f,{color:Ge[l.status]?.color||"gray",children:Ge[l.status]?.label||l.status})}),e.jsx(a.Td,{children:e.jsx(r,{size:"sm",children:R(l.createdAt)})}),e.jsx(a.Td,{children:e.jsxs(de,{position:"bottom-end",children:[e.jsx(de.Target,{children:e.jsx(le,{variant:"subtle",children:e.jsx(Gs,{size:16})})}),e.jsxs(de.Dropdown,{children:[e.jsx(de.Item,{leftSection:e.jsx(bs,{size:14}),onClick:()=>m(l),children:"Подробнее"}),l.status==="pending_payment"&&l.paymentMethod==="tbank"&&l.paymentId&&e.jsx(de.Item,{leftSection:e.jsx(De,{size:14}),color:"blue",onClick:()=>Le(l.id),children:"Проверить оплату"}),l.status==="paid"&&!I&&!se&&e.jsx(de.Item,{leftSection:e.jsx(vs,{size:14}),color:"green",onClick:()=>W(l),children:"Активировать"}),e.jsx(de.Divider,{}),e.jsx(de.Label,{children:"Изменить статус"}),l.status!=="pending_payment"&&e.jsx(de.Item,{onClick:()=>ge(l.id,"pending_payment"),children:"Ожидает оплаты"}),l.status!=="paid"&&e.jsx(de.Item,{color:"blue",onClick:()=>ge(l.id,"paid"),children:"Оплачен"}),l.status!=="in_progress"&&e.jsx(de.Item,{color:"cyan",onClick:()=>ge(l.id,"in_progress"),children:"Настраивается"}),l.status!=="active"&&e.jsx(de.Item,{color:"green",onClick:()=>ge(l.id,"active"),children:"Активен"}),l.status!=="suspended"&&e.jsx(de.Item,{color:"orange",onClick:()=>ge(l.id,"suspended"),children:"Приостановлен"}
1),l.status!=="cancelled"&&e.jsx(de.Item,{color:"red",onClick:()=>ge(l.id,"cancelled"),children:"Отменён"}),e.jsx(de.Divider,{}),e.jsx(de.Item,{color:"red",leftSection:e.jsx(Be,{size:14}),onClick:()=>Oe(l),children:"Удалить заказ"})]})]})})]},l.id)}),F.length===0&&e.jsx(a.Tr,{children:e.jsx(a.Td,{colSpan:8,children:e.jsx(r,{ta:"center",c:"dimmed",py:"xl",children:"Нет заказов"})})})]})]}),M>1&&e.jsx(i,{justify:"center",mt:"md",children:e.jsx(xs,{total:M,value:z,onChange:T})})]}),e.jsx(Se,{opened:C,onClose:U,title:`Заказ #${d?.id}`,size:"lg",children:d&&e.jsxs(B,{children:[d.kind==="protocol_addon"&&e.jsxs(ie,{color:"violet",variant:"light",icon:e.jsx(ws,{size:16}),children:[e.jsx(r,{size:"sm",fw:500,children:"Это заказ на докупку дополнительных протоколов"}),e.jsxs(r,{size:"xs",c:"dimmed",mt:4,children:["После оплаты выбранные пары «протокол × страна» автоматически добавляются к существующей компании",d.targetOrganization?.name?` «${d.targetOrganization.name}»`:"",". Кнопка «Активировать» здесь не нужна."]})]}),e.jsxs(Q,{cols:2,children:[e.jsxs("div",{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Компания"}),e.jsx(r,{fw:500,children:d.kind==="protocol_addon"&&d.targetOrganization?.name||d.companyName})]}),e.jsxs("div",{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"ИНН"}),e.jsx(r,{children:d.inn||"—"})]})]}),e.jsx(he,{label:"Контактное лицо"}),e.jsxs(Q,{cols:2,children:[e.jsxs("div",{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Имя"}),e.jsx(r,{children:d.contactName})]}),e.jsxs("div",{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Email"}),e.jsxs(i,{gap:"xs",children:[e.jsx(r,{children:d.contactEmail}),e.jsx(Je,{value:d.contactEmail,children:({copy:l})=>e.jsx(le,{size:"xs",variant:"subtle",onClick:l,children:e.jsx(Ke,{size:12})})})]})]}),d.contactPhone&&e.jsxs("div",{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Телефон"}),e.jsx(r,{children:d.contactPhone})]})]}),e.jsx(he,{label:"Детали заказа"}),e.jsxs(Q,{cols:2,children:[e.jsxs("div",{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"План"}),e.jsx(r,{fw:500,children:d.plan.name})]}),d.kind!=="protocol_addon"&&e.jsxs("div",{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Сотрудников"}),e.jsx(r,{children:d.requestedUsers})]}),e.jsxs("div",{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Сумма"}),e.jsx(r,{fw:500,children:j(d.amount)})]}),e.jsxs("div",{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Статус"}),e.jsx(f,{color:Ge[d.status]?.color,children:Ge[d.status]?.label})]})]}),d.kind!=="protocol_addon"&&d.requestedServers&&d.requestedServers.length>0&&e.jsxs("div",{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Запрошенные серверы"}),e.jsx(i,{gap:"xs",mt:"xs",children:d.requestedServers.map(l=>{const I=ts(l,"ru"),se=l.trim().toUpperCase(),Ue=I!==se;return e.jsx(Z,{label:se,disabled:!Ue,children:e.jsx(f,{variant:"outline",children:I})},l)})})]}),Array.isArray(d.selectedProtocols)&&d.selectedProtocols.length>0&&e.jsxs("div",{children:[e.jsxs(i,{justify:"space-between",align:"center",mb:"xs",children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Дополнительные протоколы"}),d.protocolsPrice?e.jsxs(r,{size:"xs",c:"dimmed",children:["на сумму ",j(d.protocolsPrice)]}):null]}
1),e.jsx(O,{p:"sm",radius:"sm",withBorder:!0,children:e.jsx(B,{gap:6,children:d.selectedProtocols.map((l,I)=>e.jsxs(i,{justify:"space-between",wrap:"nowrap",children:[e.jsxs(i,{gap:8,wrap:"nowrap",children:[e.jsx(f,{size:"sm",variant:"light",color:"violet",children:js(l.protocol)}),e.jsxs(r,{size:"sm",children:[ts(l.countryCode,"ru"),e.jsxs(r,{span:!0,size:"xs",c:"dimmed",ml:6,children:["(",l.countryCode?.toUpperCase(),")"]})]})]}),e.jsx(r,{size:"sm",fw:500,children:j(l.price||0)})]},`${l.protocol}-${l.countryCode}-${I}`))})})]}),d.comment&&e.jsxs("div",{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Комментарий клиента"}),e.jsx(O,{p:"sm",bg:"dark.6",radius:"sm",children:e.jsx(r,{size:"sm",children:d.comment})})]}),d.adminNotes&&e.jsxs("div",{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Заметки админа"}),e.jsx(O,{p:"sm",bg:"dark.6",radius:"sm",children:e.jsx(r,{size:"sm",children:d.adminNotes})})]}),d.kind!=="protocol_addon"&&d.squadName&&(()=>{const l=o.find(se=>se.name===d.squadName),I=!!l;return e.jsxs("div",{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Сквад в Remnawave"}),e.jsxs(i,{gap:6,mt:4,wrap:"wrap",children:[e.jsx(fr,{children:d.squadName}),I?e.jsx(Z,{label:`Найден в Remnawave: ${l.membersCount} пользователей, ${l.inboundsCount} inbound(ов)`,children:e.jsx(f,{size:"sm",variant:"light",color:"green",leftSection:e.jsx(we,{size:10}),children:"в Remnawave"})}):e.jsx(Z,{label:"Сквад с таким именем не найден в корпоративной Remnawave. Возможно опечатка — измените имя сквада в редакторе организации.",children:e.jsx(f,{size:"sm",variant:"light",color:"red",leftSection:e.jsx(Ps,{size:10}),children:"не найден"})})]})]})})(),e.jsx(he,{label:"История"}),e.jsxs(We,{active:-1,bulletSize:20,lineWidth:2,children:[e.jsx(We.Item,{title:"Создан",bullet:e.jsx(Bs,{size:12}),children:e.jsx(r,{size:"xs",c:"dimmed",children:R(d.createdAt)})}),d.paidAt&&e.jsxs(We.Item,{title:"Оплачен",bullet:e.jsx(wr,{size:12}),color:"green",children:[e.jsx(r,{size:"xs",c:"dimmed",children:R(d.paidAt)}),d.paymentMethod&&e.jsxs(r,{size:"xs",c:"dimmed",children:["Метод: ",d.paymentMethod]})]}),d.activatedAt&&e.jsx(We.Item,{title:"Активирован",bullet:e.jsx(we,{size:12}),color:"green",children:e.jsx(r,{size:"xs",c:"dimmed",children:R(d.activatedAt)})}),d.expiresAt&&e.jsx(We.Item,{title:"Истекает",bullet:e.jsx(Bs,{size:12}),color:"orange",children:e.jsx(r,{size:"xs",c:"dimmed",children:R(d.expiresAt)})})]}),d.kind==="protocol_addon"?e.jsxs(e.Fragment,{children:[e.jsx(he,{label:"Целевая компания"}),e.jsxs(O,{p:"md",bg:"dark.6",radius:"md",children:[d.targetOrganization?e.jsxs(Q,{cols:2,children:[e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Компания"}),e.jsx(r,{size:"sm",fw:500,children:d.targetOrganization.name})]}),d.targetOrganization.ownerEmail&&e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Email владельца"}),e.jsxs(i,{gap:"xs",children:[e.jsx(r,{size:"sm",children:d.targetOrganization.ownerEmail}),e.jsx(Je,{value:d.targetOrganization.ownerEmail,children:({copy:l})=>e.jsx(le,{size:"xs",variant:"subtle",onClick:l,children:e.jsx(Ke,{size:12})})})]})]})]}):e.jsx(r,{size:"sm",c:"dimmed",children:"Целевая компания не определена (заказ ещё не привязан)."}),e.jsx(r,{size:"xs",c:"dimmed",mt:"sm",children:"После оплаты выбранные протоколы автоматически добавятся к этой компании. Никаких ручных действий администратора не требуется."})]})]}):e.jsxs(e.Fragment,{children:[e.jsx(he,{label:"Учётные данные"}),d.organization?ce?e.jsx(O,{p:"md",bg:"dark.6",radius:"md",children:e.jsx("form",{onSubmit:G.onSubmit(t),children:e.jsxs(B,{gap:"sm",children:[e.jsx(r,{size:"sm",fw:500,children:"Изменить учётные данные"}),e.jsx(_,{label:"Email",placeholder:"[email protected]",leftSection:e.jsx(er,{size:14}),...G.getInputProps("email")}),e.jsx(As,{label:"Новый пароль",placeholder:"Оставьте пустым, чтобы не менять",leftSection:e.jsx(sr,{size:14}),...G.getInputProps("newPassword")}
1),e.jsx(ie,{color:"yellow",variant:"light",children:"Новые данные будут отправлены на указанный email"}),e.jsxs(i,{justify:"flex-end",children:[e.jsx(v,{variant:"subtle",onClick:()=>Y(!1),children:"Отмена"}),e.jsx(v,{type:"submit",loading:re,children:"Сохранить"})]})]})})}):e.jsxs(O,{p:"md",bg:"dark.6",radius:"md",children:[e.jsxs(i,{justify:"space-between",mb:"sm",children:[e.jsx(r,{size:"sm",fw:500,children:"Данные для входа в корп. портал"}),e.jsx(v,{size:"xs",variant:"light",leftSection:e.jsx(Ye,{size:14}),onClick:Fe,children:"Изменить"})]}),e.jsxs(Q,{cols:2,children:[e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Email"}),e.jsxs(i,{gap:"xs",children:[e.jsx(r,{size:"sm",children:d.organization.ownerEmail||d.contactEmail}),e.jsx(Je,{value:d.organization.ownerEmail||d.contactEmail,children:({copy:l})=>e.jsx(le,{size:"xs",variant:"subtle",onClick:l,children:e.jsx(Ke,{size:12})})})]})]}),e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Пароль"}),e.jsx(r,{size:"sm",c:"dimmed",children:"••••••••"})]})]})]}):d.targetOrganization?e.jsx(ie,{color:"teal",variant:"light",icon:e.jsx(De,{size:16}),title:"Заказ на продление",children:e.jsxs(r,{size:"sm",children:["Это продление подписки компании",d.targetOrganization.name?` «${d.targetOrganization.name}»`:"",". После оплаты срок действующей организации продлевается автоматически — новую организацию создавать НЕ нужно, кнопки «Активировать» здесь нет."]})}):e.jsxs(ie,{color:"orange",variant:"light",title:"Организация не создана",children:[e.jsx(r,{size:"sm",mb:"sm",children:'Для создания учётных данных нужно активировать заказ через кнопку "Активировать" в меню.'}),e.jsx(v,{size:"xs",color:"green",leftSection:e.jsx(vs,{size:14}),onClick:()=>{U(),W(d)},children:"Активировать сейчас"})]})]})]})}),e.jsx(Se,{opened:x,onClose:y,title:"Активировать заказ",children:e.jsx("form",{onSubmit:X.onSubmit(te),children:e.jsxs(B,{children:[e.jsxs(r,{size:"sm",children:["Активация заказа для ",e.jsx("strong",{children:d?.companyName})]}),e.jsx(r,{size:"sm",c:"dimmed",children:"Перед активацией убедитесь, что сквад создан в Remnawave с нужными серверами."}),o.length>0?e.jsx(Te,{label:"Сквад в Remnawave",placeholder:"Выберите существующий сквад",required:!0,searchable:!0,data:o.map(l=>({value:l.name,label:`${l.name} · ${l.membersCount} польз. · ${l.inboundsCount} inb.`})),description:"Список загружен из корпоративной Remnawave — опечатки исключены",...X.getInputProps("squadName")}):e.jsx(_,{label:"Название сквада в Remnawave",placeholder:"company_name",description:"Не удалось получить список сквадов из Remnawave — введите имя вручную (без префикса panel)",required:!0,...X.getInputProps("squadName")}),e.jsx(Ce,{label:"Заметки",placeholder:"Настроил серверы RU, DE, NL...",...X.getInputProps("adminNotes")}),e.jsxs(i,{justify:"flex-end",mt:"md",children:[e.jsx(v,{variant:"subtle",onClick:y,children:"Отмена"}),e.jsx(v,{type:"submit",color:"green",leftSection:e.jsx(we,{size:16}),children:"Активировать"})]})]})})}),e.jsx(Se,{opened:K,onClose:ee,title:"Удалить заказ?",size:"md",children:V&&e.jsxs(B,{children:[e.jsx(ie,{color:"red",variant:"light",icon:e.jsx(rr,{size:16}),children:e.jsxs(r,{size:"sm",children:["Заказ ",e.jsxs("strong",{children:["#",V.id]})," для"," ",e.jsx("strong",{children:V.companyName})," будет удалён безвозвратно."]})}),V.organization&&e.jsx(r,{size:"sm",c:"dimmed",children:"Заказ привязан к активной организации. Сама организация и её сотрудники удалены не будут — удалится только запись о заказе."}),e.jsxs(i,{justify:"flex-end",mt:"md",children:[e.jsx(v,{variant:"subtle",onClick:ee,disabled:be,children:"Отмена"}),e.jsx(v,{color:"red",leftSection:e.jsx(Be,{size:16}),loading:be,onClick:fe,children:"Удалить"})]})]})})]});return c?ye:e.jsx(ks,{size:"xl",py:"xl",children:ye})}const as=c=>c.split(/\r?\n/).map(k=>
1k.trim()).filter(Boolean),qe=c=>c.join(`
2`);function Lr(){const{token:c}=Re(),[k,N]=n.useState([]),[$,F]=n.useState(!0),[g,D]=n.useState(null),[h,d]=n.useState(null),[u,S]=n.useState(!1),[A,z]=n.useState(!1),[T,M]=n.useState("off"),[q,C]=n.useState(""),[H,U]=n.useState(""),[x,E]=n.useState([]),[y,K]=n.useState({}),[w,ee]=n.useState(null),[V,L]=n.useState(null),[be,ve]=n.useState(!1),[ce,Y]=n.useState(!1),[re,s]=n.useState(!1),[o,P]=n.useState("off"),[G,X]=n.useState(""),[Ne,pe]=n.useState(""),[m,W]=n.useState(!1),[te,ge]=n.useState(null),[Le,Oe]=n.useState(!1);n.useEffect(()=>{fe()},[]),n.useEffect(()=>{g?(Fe(g),t(g),j(g),ee(null),L(null)):(d(null),E([]),K({}))},[g]),n.useEffect(()=>{g&&w?R(g,w):L(null)},[g,w]);const fe=async()=>{F(!0);try{const b=await fetch("/api/admin/corporate/organizations",{headers:{Authorization:`Bearer ${c}`}});b.ok&&N(await b.json())}catch(b){console.error(b)}finally{F(!1)}},Fe=async b=>{S(!0);try{const J=await fetch(`/api/admin/corporate/organizations/${b}/access-policy`,{headers:{Authorization:`Bearer ${c}`}});if(!J.ok)throw new Error("Не удалось загрузить политику");const ae=await J.json();d(ae),M(ae.mode),C(qe(ae.allowedDomains)),U(qe(ae.blockedDomains))}catch(J){p.show({title:"Ошибка",message:J.message,color:"red"})}finally{S(!1)}},t=async b=>{try{const J=await fetch(`/api/admin/corporate/members?organizationId=${b}&limit=100`,{headers:{Authorization:`Bearer ${c}`}});if(!J.ok)return;const ae=await J.json(),me=Array.isArray(ae)?ae:ae?.items||ae?.members||[];E(me)}catch(J){console.error(J)}},j=async b=>{try{const J=await fetch(`/api/admin/corporate/organizations/${b}/access-policy/members/overrides`,{headers:{Authorization:`Bearer ${c}`}});if(!J.ok)return;const ae=await J.json(),me={};ae.forEach(rs=>{me[String(rs.memberId)]={mode:rs.mode,allowedCount:rs.allowedCount,blockedCount:rs.blockedCount}}),K(me)}catch(J){console.error(J)}},R=async(b,J)=>{ve(!0);try{const ae=await fetch(`/api/admin/corporate/organizations/${b}/access-policy/members/${J}`,{headers:{Authorization:`Bearer ${c}`}});if(!ae.ok)throw new Error("Не удалось загрузить override");const me=await ae.json();L(me),s(me.hasOverride),me.hasOverride&&me.override?(P(me.override.mode??"off"),X(qe(me.override.allowedDomains)),pe(qe(me.override.blockedDomains))):(P(me.effective.mode),X(qe(me.effective.allowedDomains)),pe(qe(me.effective.blockedDomains)))}catch(ae){p.show({title:"Ошибка",message:ae.message,color:"red"})}finally{ve(!1)}},ye=async()=>{if(g){z(!0);try{const b=await fetch(`/api/admin/corporate/organizations/${g}/access-policy`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`},body:JSON.stringify({mode:T,allowedDomains:as(q),blockedDomains:as(H)})});if(!b.ok){const ae=await b.json().catch(()=>({})),me=Array.isArray(ae?.invalid)?` — ${ae.invalid.slice(0,3).join(", ")}…`:"";throw new Error(`${ae?.message||"Save failed"}${me}`)}const J=await b.json();d(J),M(J.mode),C(qe(J.allowedDomains)),U(qe(J.blockedDomains)),p.show({title:"Сохранено",message:"Политика организации обновлена",color:"teal"})}catch(b){p.show({title:"Ошибка",message:b.message,color:"red"})}finally{z(!1)}}},l=async()=>{if(!(!g||!w)){Y(!0);try{const b=re?{mode:o,allowedDomains:as(G),blockedDomains:as(Ne)}:{mode:"inherit"},J=await fetch(`/api/admin/corporate/organizations/${g}/access-policy/members/${w}`,{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`},body:JSON.stringify(b)});if(!J.ok){const ae=await J.json().catch(()=>({})),me=Array.isArray(ae?.invalid)?` — ${ae.invalid.slice(0,3).join(", ")}…`:"";throw new Error(`${ae?.message||"Save failed"}${me}`)}p.show({title:"Сохранено",message:re?"Override применён":"Override снят",color:"teal"}),await R(g,w),await j(g)}catch(b){p.show({title:"Ошибка",message:b.message,color:"red"})}finally{Y(!1)}}},I=async()=>{if(g){W(!0);try{const b=await fetch(`/api/admin/corporate/organizations/${g}/access-policy/sync`,{method:"POST",headers:{Authorization:`Bearer ${c}`}});if(!b.ok)throw new Error("Sync failed");const J=await b.json();p.show({title:"Синхронизация запущена",message:`Пушим в ${J.pushedProfiles} профил${J.pushedProfiles===1?"ь":"я"}, ${J.rules} правил`,color:"teal"})}catch(b){p.show({title:"Ошибка",message:b.message,color:"red"})}finally{W(!1)}}},se=async()=>
2{if(g){Oe(!0);try{const b=await fetch(`/api/admin/corporate/organizations/${g}/access-policy/preview`,{headers:{Authorization:`Bearer ${c}`}});if(!b.ok)throw new Error("Preview failed");ge(await b.json())}catch(b){p.show({title:"Ошибка",message:b.message,color:"red"})}finally{Oe(!1)}}},Ue=async()=>{if(!(!g||!w)){Y(!0);try{if(!(await fetch(`/api/admin/corporate/organizations/${g}/access-policy/members/${w}`,{method:"DELETE",headers:{Authorization:`Bearer ${c}`}})).ok)throw new Error("Не удалось снять override");p.show({title:"Override снят",message:"",color:"teal"}),await R(g,w),await j(g)}catch(b){p.show({title:"Ошибка",message:b.message,color:"red"})}finally{Y(!1)}}},Me=n.useMemo(()=>k.map(b=>({value:String(b.id),label:b.name+(b.isActive?"":" (неактивна)")})),[k]);return e.jsxs(B,{gap:"lg",children:[e.jsxs(i,{justify:"space-between",children:[e.jsxs(i,{children:[e.jsx(ws,{size:22}),e.jsx(ke,{order:4,children:"Доступ к сайтам"})]}),e.jsx(Z,{label:"Обновить",children:e.jsx(le,{variant:"light",onClick:()=>{fe(),g&&(Fe(g),t(g),j(g))},children:e.jsx(De,{size:16})})})]}),e.jsx(Te,{label:"Организация",placeholder:$?"Загрузка…":"Выберите организацию",data:Me,value:g,onChange:D,searchable:!0,nothingFoundMessage:"Нет совпадений",leftSection:e.jsx(Ie,{size:16}),maxDropdownHeight:400,disabled:$}),g?u?e.jsx($e,{py:"xl",children:e.jsx(Pe,{})}):e.jsxs(B,{gap:"lg",children:[e.jsxs(je,{withBorder:!0,p:"lg",radius:"md",children:[e.jsxs(i,{justify:"space-between",mb:"sm",children:[e.jsxs(i,{children:[e.jsx(Ie,{size:18}),e.jsx(ke,{order:5,children:"Политика организации"})]}),h?.updatedAt&&e.jsxs(r,{size:"xs",c:"dimmed",children:["Обновлено: ",new Date(h.updatedAt).toLocaleString("ru-RU")]})]}),e.jsx(ys,{value:T,onChange:b=>M(b),data:[{value:"off",label:e.jsxs(i,{gap:6,wrap:"nowrap",justify:"center",children:[e.jsx(zs,{size:14}),e.jsx("span",{children:"Off"})]})},{value:"allowlist",label:e.jsxs(i,{gap:6,wrap:"nowrap",justify:"center",children:[e.jsx(ms,{size:14}),e.jsx("span",{children:"Allowlist"})]})},{value:"denylist",label:e.jsxs(i,{gap:6,wrap:"nowrap",justify:"center",children:[e.jsx(jr,{size:14}),e.jsx("span",{children:"Denylist"})]})}]}),e.jsx(Ce,{label:"Разрешённые домены",description:"По одному на строку",autosize:!0,minRows:3,maxRows:10,mt:"sm",value:q,onChange:b=>C(b.target.value),styles:{input:{fontFamily:"monospace",fontSize:12}},disabled:T==="denylist"}),e.jsx(Ce,{label:"Запрещённые домены",description:"По одному на строку",autosize:!0,minRows:3,maxRows:10,mt:"sm",value:H,onChange:b=>U(b.target.value),styles:{input:{fontFamily:"monospace",fontSize:12}},disabled:T==="allowlist"}),e.jsxs(i,{justify:"space-between",mt:"md",children:[e.jsxs(i,{gap:"xs",children:[e.jsx(v,{variant:"light",leftSection:e.jsx(br,{size:14}),loading:Le,onClick:se,children:"Предпросмотр правил"}),e.jsx(v,{variant:"light",color:"teal",leftSection:e.jsx(_s,{size:14}),loading:m,onClick:I,children:"Синхронизация"})]}),e.jsx(v,{leftSection:e.jsx(Ss,{size:16}),loading:A,onClick:ye,children:"Сохранить политику организации"})]}
2),te&&e.jsxs(O,{p:"sm",radius:"md",withBorder:!0,mt:"md",style:{background:"rgba(0,0,0,0.2)"},children:[e.jsxs(i,{justify:"space-between",mb:"xs",children:[e.jsxs(r,{size:"xs",c:"dimmed",children:["Скомпилировано: ",te.stats?.members??0," сотрудников, ",te.stats?.buckets??0," групп"]}),e.jsxs(r,{size:"xs",c:"dimmed",children:["Правил: ",te.rules?.length??0]})]}),e.jsx(Ze,{h:200,children:e.jsx(Ee,{component:"pre",style:{fontFamily:"monospace",fontSize:11,whiteSpace:"pre-wrap",margin:0},children:JSON.stringify(te.rules??[],null,2)})})]})]}),e.jsxs(je,{withBorder:!0,p:"lg",radius:"md",children:[e.jsxs(i,{justify:"space-between",mb:"sm",children:[e.jsxs(i,{children:[e.jsx(ss,{size:18}),e.jsx(ke,{order:5,children:"Индивидуальные правила сотрудников"})]}),e.jsxs(r,{size:"sm",c:"dimmed",children:["Override: ",Object.keys(y).length," / ",x.length]})]}),e.jsxs(i,{align:"flex-start",gap:"md",wrap:"nowrap",children:[e.jsxs(Ee,{style:{flex:"0 0 280px"},children:[e.jsx(r,{size:"xs",c:"dimmed",mb:6,children:"Сотрудники"}),e.jsx(Ze,{h:400,children:e.jsxs(B,{gap:4,children:[x.length===0&&e.jsx(r,{size:"sm",c:"dimmed",children:"В этой организации нет сотрудников."}),x.map(b=>{const J=y[String(b.id)],ae=String(b.id)===w;return e.jsx(O,{p:"xs",radius:"md",withBorder:!0,onClick:()=>ee(String(b.id)),style:{cursor:"pointer",borderColor:ae?"var(--mantine-color-blue-5)":void 0,background:ae?"rgba(34, 139, 230, 0.08)":void 0},children:e.jsxs(i,{justify:"space-between",wrap:"nowrap",children:[e.jsxs(Ee,{style:{minWidth:0,flex:1},children:[e.jsx(r,{size:"sm",fw:500,truncate:!0,title:b.user?.email,children:b.user?.name||b.user?.email}),e.jsx(r,{size:"xs",c:"dimmed",truncate:!0,children:b.user?.email})]}),J&&e.jsx(Z,{label:`${J.mode} · allow=${J.allowedCount} · deny=${J.blockedCount}`,children:e.jsx(f,{size:"xs",color:"grape",variant:"light",children:J.mode})})]})},b.id)})]})})]}),e.jsx(Ee,{style:{flex:1,minWidth:0},children:w?be?e.jsx($e,{py:"xl",children:e.jsx(Pe,{})}):V?e.jsxs(B,{gap:"sm",children:[e.jsx(ie,{icon:e.jsx(Ae,{size:14}),color:V.hasOverride?"grape":"gray",variant:"light",p:"xs",children:e.jsxs(r,{size:"xs",children:["Сейчас:"," ",e.jsx("strong",{children:V.effective.source==="override"?"override":"политика организации"})," · ","режим: ",e.jsx("strong",{children:V.effective.mode})]})}),e.jsx(Xe,{label:"Задать индивидуальные правила",checked:re,onChange:b=>s(b.currentTarget.checked)}),re&&e.jsxs(e.Fragment,{children:[e.jsx(ys,{value:o,onChange:b=>P(b),data:[{value:"off",label:"Off"},{value:"allowlist",label:"Allowlist"},{value:"denylist",label:"Denylist"}]}),e.jsx(Ce,{label:"Разрешённые",autosize:!0,minRows:3,maxRows:8,value:G,onChange:b=>X(b.target.value),styles:{input:{fontFamily:"monospace",fontSize:12}},disabled:o==="denylist"}),e.jsx(Ce,{label:"Запрещённые",autosize:!0,minRows:3,maxRows:8,value:Ne,onChange:b=>pe(b.target.value),styles:{input:{fontFamily:"monospace",fontSize:12}},disabled:o==="allowlist"})]}),e.jsxs(i,{justify:"space-between",mt:"sm",children:[V.hasOverride?e.jsx(v,{variant:"subtle",color:"red",leftSection:e.jsx(Be,{size:14}),onClick:Ue,loading:ce,children:"Удалить override"}):e.jsx(Ee,{}),e.jsx(v,{leftSection:e.jsx(Ss,{size:14}),loading:ce,onClick:l,children:"Сохранить"})]})]}):null:e.jsx(ie,{icon:e.jsx(ds,{size:16}),color:"gray",variant:"light",children:"Выберите сотрудника слева, чтобы задать индивидуальные правила."})})]})]})]}):e.jsx(ie,{icon:e.jsx(ir,{size:16}),color:"blue",variant:"light",children:"Выберите организацию, чтобы посмотреть/изменить её политику."})]})}oe.extend(tr);const Nr=15;function Fr(){const{token:c}=Re(),[k,N]=n.useState(!1),[$,F]=n.useState(null),[g,D]=n.useState(null),[h,d]=n.useState(null),[u,S]=n.useState("idle"),A=n.useRef(null),z=n.useRef(null),[T,M]=n.useState(""),[q,C]=n.useState(""),[H,U]=n.useState(null),[x,E]=n.useState(null),[y,K]=n.useState("idle"),[w,ee]=n.useState(""),V=async()=>{N(!0);try{const s=await fetch("/api/admin/corporate/nodes",{headers:{Authorization:`Bearer ${c}`}});if(!s.ok)throw new Error("Не удалось получить список нод");F(await s.json())}catch(s){p.show({title:"Ошибка",message:s.message,color:"red"})}finally{N(!1)}};n.useEffect(()=>{V()},[]),n.useEffect(()=>{const s=()=>{A.current&&(clearInterval(A.current),A.current=null),z.current&&(clearTimeout(z.current),z.current=null)};if(!h){s(),S("idle");return}const o=h.remnawaveUuid;S("waiting");const P=async()=>{try{const G=await fetch("/api/admin/corporate/nodes",{headers:{Authorization:`Bearer ${c}`}});if(!G.ok)return;const X=await G.json(),pe=X.nodes.find(m=>m.remnawaveUuid===o)?.adoptedNode?.lastSeenAt??null;pe&&!ce(pe)&&(s(),S("connected"),F(X))}catch{}};return P(),A.current=setInterval(P,5e3),z.current=setTimeout(()=>{s(),S(G=>G==="connected"?G:"timeout")},18e4),s}
2,[h]);const L=async s=>{try{const o=await fetch(`/api/admin/corporate/nodes/${s}/adopt`,{method:"POST",headers:{Authorization:`Bearer ${c}`,"Content-Type":"application/json"},body:JSON.stringify({hostname:T||void 0,publicIp:q||void 0})});if(!o.ok){const G=await o.json().catch(()=>({}));throw new Error(G?.message||"Adopt failed")}const P=await o.json();d(P),D(null),M(""),C(""),await V()}catch(o){p.show({title:"Ошибка",message:o.message,color:"red"})}},be=async s=>{try{if(!(await fetch(`/api/admin/corporate/nodes/${s}`,{method:"DELETE",headers:{Authorization:`Bearer ${c}`}})).ok)throw new Error("Не удалось отозвать токен");p.show({title:"Готово",message:"Ingestion token отозван",color:"green"}),await V()}catch(o){p.show({title:"Ошибка",message:o.message,color:"red"})}finally{U(null)}},ve=async s=>{K("running"),ee("");try{const o=await fetch(`/api/admin/corporate/nodes/${s}/install-logger`,{method:"POST",headers:{Authorization:`Bearer ${c}`,"Content-Type":"application/json"}}),P=await o.json().catch(()=>({}));if(!o.ok)throw new Error(P?.message||"Установка не удалась");ee(P.log||"(пустой вывод)"),K("done"),p.show({title:"Готово",message:`Логгер установлен на ${P.ip||"ноду"}`,color:"green"}),await V()}catch(o){ee(o.message||String(o)),K("error"),p.show({title:"Ошибка",message:o.message,color:"red"})}},ce=s=>s?oe().diff(oe(s),"minute")>Nr:!0,Y=s=>{const o=s.adoptedNode,P=o?ce(o.lastSeenAt):null;return e.jsxs(a.Tr,{children:[e.jsxs(a.Td,{children:[e.jsx(r,{fw:500,children:s.name||s.remnawaveUuid.slice(0,8)}),e.jsx(r,{size:"xs",c:"dimmed",children:s.remnawaveUuid})]}),e.jsxs(a.Td,{children:[e.jsx(r,{size:"sm",children:s.address||"—"}),e.jsx(r,{size:"xs",c:"dimmed",children:s.countryCode||""})]}),e.jsx(a.Td,{children:s.isOnline===!0?e.jsx(f,{color:"green",children:"online"}):s.isOnline===!1?e.jsx(f,{color:"gray",children:"offline"}):e.jsx(f,{color:"gray",variant:"light",children:"—"})}),e.jsxs(a.Td,{children:[o?P?e.jsx(f,{color:"orange",children:e.jsxs(i,{gap:4,children:[e.jsx(us,{size:12}),"Стейл: ",o.lastSeenAt?oe(o.lastSeenAt).fromNow():"—"]})}):e.jsx(f,{color:"green",children:e.jsxs(i,{gap:4,children:[e.jsx(us,{size:12}),o.lastSeenAt?oe(o.lastSeenAt).fromNow():"неизвестно"]})}):e.jsx(f,{color:"gray",variant:"light",children:e.jsxs(i,{gap:4,children:[e.jsx(Or,{size:12})," Не адаптировано"]})}),o&&e.jsxs(r,{size:"xs",c:"dimmed",mt:4,children:["token …",o.ingestTokenPrefix,"  •  vector: ",o.vectorVersion||"?"]})]}),e.jsx(a.Td,{children:e.jsxs(i,{gap:"xs",wrap:"nowrap",children:[e.jsx(v,{size:"xs",variant:o?"default":"filled",onClick:()=>{D(s.remnawaveUuid),M(s.name||""),C(s.address||"")},children:o?"Ротировать токен":"Adopt"}),e.jsx(Z,{label:"Подключиться к ноде по SSH (доступ из remna-nodes) и установить Vector автоматически",children:e.jsx(v,{size:"xs",variant:"light",color:"blue",leftSection:e.jsx(vr,{size:12}),onClick:()=>{E({uuid:s.remnawaveUuid,name:s.name||s.remnawaveUuid}),K("idle"),ee(""),ve(s.remnawaveUuid)},children:"Установить по SSH"})}),o&&e.jsx(Z,{label:"Отозвать токен (нода перестанет слать логи)",children:e.jsx(v,{size:"xs",color:"red",variant:"light",leftSection:e.jsx(Be,{size:12}),onClick:()=>U({uuid:s.remnawaveUuid,name:s.name||s.remnawaveUuid}),children:"Revoke"})})]})})]},s.remnawaveUuid)},re=n.useMemo(()=>$?.nodes.find(s=>s.remnawaveUuid===g)??null,[$,g]);return e.jsxs(B,{gap:"md",children:[e.jsxs(i,{justify:"space-between",children:[e.jsxs("div",{children:[e.jsxs(i,{gap:"xs",children:[e.jsx(Is,{size:22}),e.jsx(ke,{order:3,children:"Корпоративные ноды"})]}),e.jsx(r,{c:"dimmed",size:"sm",mt:4,children:"Все ноды корпоративного Remnawave + статус Vector-логгера для каждой."})]}),e.jsx(v,{leftSection:e.jsx(De,{size:14}),variant:"light",onClick:V,loading:k,children:"Обновить"})]}),$?.panelError&&e.jsxs(ie,{color:"orange",icon:e.jsx(Ae,{size:16}),children:["Корпоративный Remnawave недоступен: ",$.panelError,". Показаны только адаптированные ноды."]}),k&&!$?e.jsx($e,{py:"xl",children:e.jsx(Pe,{})}):$?e.jsx(je,{withBorder:!0,children:e.jsxs(a,{striped:!0,highlightOnHover:!0,children:[e.jsx(a.Thead,{children:e.jsxs(a.Tr,{children:[e.jsx(a.Th,{children:"Нода"}),e.jsx(a.Th,{children:"Адрес"}),e.jsx(a.Th,{children:"Remnawave"}),e.jsx(a.Th,{children:"Логирование"}),e.jsx(a.Th,{})]})}),e.jsx(a.Tbody,{children:$.nodes.length===0?e.jsx(a.Tr,{children:e.jsx(a.Td,{colSpan:5,children:e.jsx(r,{c:"dimmed",ta:"center",py:"md",children:"В корпоративной панели Remnawave пока нет нод."})})}):$.nodes.map(Y)})]})}
2):e.jsx(ie,{color:"gray",icon:e.jsx(Ae,{size:16}),children:"Нет данных"}),$&&$.orphan.length>0&&e.jsxs(je,{withBorder:!0,children:[e.jsx(ke,{order:5,mb:"xs",children:"«Осиротевшие» токены"}),e.jsx(r,{size:"sm",c:"dimmed",mb:"sm",children:"Ноды удалены из corp Remnawave, но токены ещё активны. Рекомендуется отозвать."}),e.jsx(a,{children:e.jsx(a.Tbody,{children:$.orphan.map(s=>e.jsxs(a.Tr,{children:[e.jsxs(a.Td,{children:[e.jsx(r,{children:s.adoptedNode.hostname||s.remnawaveUuid}),e.jsxs(r,{size:"xs",c:"dimmed",children:["…",s.adoptedNode.ingestTokenPrefix]})]}),e.jsx(a.Td,{ta:"right",children:e.jsx(v,{size:"xs",color:"red",variant:"light",onClick:()=>U({uuid:s.remnawaveUuid,name:s.adoptedNode.hostname||s.remnawaveUuid}),children:"Revoke"})})]},s.adoptedNode.id))})})]}),e.jsx(Se,{opened:!!g,onClose:()=>D(null),title:re?.adopted?"Ротация ingestion-токена":"Adopt-flow: подключить логирование",size:"lg",children:re&&e.jsxs(B,{gap:"sm",children:[e.jsxs(ie,{color:"blue",icon:e.jsx(Ae,{size:16}),children:["Будет сгенерирован новый ingestion-токен.",re.adopted?" Старый токен немедленно перестанет работать.":" Это разовое действие — токен будет показан только сейчас."]}),e.jsx(_,{label:"Hostname (опционально)",value:T,onChange:s=>M(s.currentTarget.value),placeholder:"например: corp-fi-1"}),e.jsx(_,{label:"Public IP (опционально)",value:q,onChange:s=>C(s.currentTarget.value),placeholder:"например: 1.2.3.4"}),e.jsxs(i,{justify:"flex-end",children:[e.jsx(v,{variant:"default",onClick:()=>D(null),children:"Отмена"}),e.jsx(v,{onClick:()=>L(re.remnawaveUuid),children:re.adopted?"Ротировать":"Adopt"})]})]})}),e.jsx(Se,{opened:!!h,onClose:()=>d(null),title:"Токен создан — скопируйте сейчас",size:"xl",children:h&&e.jsxs(B,{gap:"sm",children:[e.jsx(ie,{color:"yellow",icon:e.jsx(Ae,{size:16}),children:"Этот токен показан один раз. Сохраните установочную команду и выполните её на VPS."}),e.jsx(O,{p:"sm",withBorder:!0,bg:"dark.6",children:e.jsx(r,{ff:"monospace",size:"sm",style:{wordBreak:"break-all",whiteSpace:"pre-wrap"},children:h.installCommand})}),e.jsx(i,{justify:"flex-end",children:e.jsx(Je,{value:h.installCommand,timeout:2e3,children:({copied:s,copy:o})=>e.jsx(v,{onClick:o,leftSection:s?e.jsx(we,{size:14}):e.jsx(Ke,{size:14}),color:s?"green":"blue",children:s?"Скопировано":"Скопировать команду"})})}),u==="connected"?e.jsx(ie,{color:"green",icon:e.jsx(us,{size:16}),children:"Нода на связи — Vector подключился, логи поступают."}):u==="timeout"?e.jsxs(ie,{color:"orange",icon:e.jsx(Ae,{size:16}),children:["Vector пока не достучался. Выполните команду на сервере и проверьте контейнер:"," ",e.jsx(r,{span:!0,ff:"monospace",size:"sm",children:"docker logs -f corp-vector"})]}):e.jsx(ie,{color:"blue",icon:e.jsx(Pe,{size:14}),children:"Ожидаем первое подключение Vector… Выполните команду на сервере — статус обновится автоматически."}),e.jsxs(r,{size:"xs",c:"dimmed",children:["UUID ноды: ",h.remnawaveUuid," • token: ",h.ingestToken.slice(0,8),"…"]})]})}),e.jsx(Se,{opened:!!x,onClose:()=>{y!=="running"&&E(null)},title:`Установка логгера по SSH: ${x?.name??""}`,size:"xl",closeOnClickOutside:y!=="running",withCloseButton:y!=="running",children:e.jsxs(B,{gap:"sm",children:[y==="running"&&e.jsx(ie,{color:"blue",icon:e.jsx(Pe,{size:14}),children:"Подключаемся к ноде и ставим Vector… На первой установке скачивается образ — это может занять несколько минут. Не закрывайте окно."}
2),y==="done"&&e.jsx(ie,{color:"green",icon:e.jsx(we,{size:16}),children:"Готово — Vector установлен и запущен на ноде. Статус обновится в таблице."}),y==="error"&&e.jsx(ie,{color:"red",icon:e.jsx(Ae,{size:16}),children:"Установка не удалась. Подробности ниже — при необходимости можно выполнить команду на сервере вручную (кнопка Adopt)."}),w&&e.jsx(O,{p:"sm",withBorder:!0,bg:"dark.6",style:{maxHeight:360,overflow:"auto"},children:e.jsx(r,{ff:"monospace",size:"xs",style:{whiteSpace:"pre-wrap",wordBreak:"break-all"},children:w})}),e.jsx(i,{justify:"flex-end",children:e.jsx(v,{variant:"default",disabled:y==="running",onClick:()=>E(null),children:"Закрыть"})})]})}),e.jsx(Se,{opened:!!H,onClose:()=>U(null),title:"Отозвать ingestion token?",children:e.jsxs(B,{children:[e.jsxs(r,{children:["Нода ",e.jsx("b",{children:H?.name})," перестанет отправлять логи. Чтобы возобновить, потребуется заново выполнить adopt и переустановить Vector."]}),e.jsxs(i,{justify:"flex-end",children:[e.jsx(v,{variant:"default",onClick:()=>U(null),children:"Отмена"}),e.jsx(v,{color:"red",onClick:()=>{if(!H)return;const s=$?.nodes.find(o=>o.remnawaveUuid===H.uuid)?.adoptedNode||$?.orphan.find(o=>o.remnawaveUuid===H.uuid)?.adoptedNode;s&&be(s.id)},children:"Отозвать"})]})]})})]})}const ps=100;function qr(){const{token:c}=Re(),[k,N]=n.useState([]),[$,F]=n.useState(null),[g,D]=n.useState(""),[h,d]=n.useState([null,null]),[u,S]=n.useState(1),[A,z]=n.useState(!1),[T,M]=n.useState(null),q=n.useMemo(()=>T?Math.max(1,Math.ceil(T.total/ps)):1,[T]);n.useEffect(()=>{C()},[]),n.useEffect(()=>{H()},[u,$]);const C=async()=>{try{const y=await fetch("/api/admin/corporate/organizations",{headers:{Authorization:`Bearer ${c}`}});if(y.ok){const K=await y.json();N(K.map(w=>({id:String(w.id),name:w.name})))}}catch(y){console.error(y)}},H=async()=>{z(!0);try{const y=new URLSearchParams;y.set("limit",String(ps)),y.set("offset",String((u-1)*ps)),$&&y.set("orgId",$),g.trim()&&y.set("domain",g.trim()),h[0]&&y.set("from",h[0].toISOString()),h[1]&&y.set("to",h[1].toISOString());const K=await fetch(`/api/admin/corporate/access-log?${y}`,{headers:{Authorization:`Bearer ${c}`}});if(!K.ok)throw new Error("Не удалось получить журнал");M(await K.json())}catch(y){p.show({title:"Ошибка",message:y.message,color:"red"})}finally{z(!1)}},U=()=>{S(1),H()},x=y=>{const K=y==null?"":String(y);return`"${(/^[=+\-@|!\t\r]/.test(K)?"	"+K:K).replace(/"/g,'""')}"`},E=()=>{if(!T||T.items.length===0)return;const y=[["occurredAt","email","domain","action","memberEmail","nodeHostname"].map(x).join(","),...T.items.map(V=>[V.occurredAt,V.email,V.domain,V.action,V.memberEmail??"",V.nodeHostname??""].map(x).join(","))],K=new Blob([y.join(`
3`)],{type:"text/csv;charset=utf-8"}),w=URL.createObjectURL(K),ee=document.createElement("a");ee.href=w,ee.download=`corp-access-log-${oe().format("YYYYMMDD-HHmmss")}.csv`,ee.click(),setTimeout(()=>URL.revokeObjectURL(w),1e3)};return e.jsxs(B,{gap:"md",children:[e.jsxs(i,{justify:"space-between",children:[e.jsxs("div",{children:[e.jsxs(i,{gap:"xs",children:[e.jsx($s,{size:22}),e.jsx(ke,{order:3,children:"Журнал доступа"})]}),e.jsx(r,{c:"dimmed",size:"sm",mt:4,children:"Заблокированные запросы со всех корпоративных нод. Ретеншн 90 дней."})]}),e.jsxs(i,{children:[e.jsx(v,{leftSection:e.jsx(ar,{size:14}),variant:"light",onClick:E,disabled:!T||T.items.length===0,children:"Экспорт CSV"}),e.jsx(v,{leftSection:e.jsx(De,{size:14}),variant:"light",onClick:()=>H(),loading:A,children:"Обновить"})]})]}),e.jsx(je,{withBorder:!0,children:e.jsxs(i,{grow:!0,align:"end",children:[e.jsx(Te,{label:"Организация",placeholder:"Все",clearable:!0,data:k.map(y=>({value:y.id,label:y.name})),value:$,onChange:y=>{S(1),F(y)},searchable:!0}),e.jsx(_,{label:"Домен содержит",placeholder:"facebook",value:g,onChange:y=>D(y.currentTarget.value),onKeyDown:y=>y.key==="Enter"&&U()}),e.jsx(Ws,{type:"range",label:"Период",value:h,onChange:d,clearable:!0}),e.jsx(v,{leftSection:e.jsx(yr,{size:14}),onClick:U,children:"Применить"})]})}),A&&!T?e.jsx($e,{py:"xl",children:e.jsx(Pe,{})}):T?e.jsxs(je,{withBorder:!0,children:[e.jsxs(i,{justify:"space-between",mb:"xs",children:[e.jsxs(r,{size:"sm",c:"dimmed",children:["Всего: ",e.jsx("b",{children:T.total})]}),e.jsxs(r,{size:"sm",c:"dimmed",children:["Страница ",u," / ",q]})]}),e.jsxs(a,{striped:!0,highlightOnHover:!0,children:[e.jsx(a.Thead,{children:e.jsxs(a.Tr,{children:[e.jsx(a.Th,{children:"Время"}),e.jsx(a.Th,{children:"Сотрудник"}),e.jsx(a.Th,{children:"Домен"}),e.jsx(a.Th,{children:"Действие"}),e.jsx(a.Th,{children:"Нода"})]})}),e.jsx(a.Tbody,{children:T.items.length===0?e.jsx(a.Tr,{children:e.jsx(a.Td,{colSpan:5,children:e.jsx(r,{c:"dimmed",ta:"center",py:"md",children:"Нет событий"})})}):T.items.map(y=>e.jsxs(a.Tr,{children:[e.jsx(a.Td,{children:e.jsx(r,{size:"sm",children:oe(y.occurredAt).format("DD.MM HH:mm:ss")})}),e.jsxs(a.Td,{children:[e.jsx(r,{size:"sm",children:y.memberName||y.memberEmail||y.email}),e.jsx(r,{size:"xs",c:"dimmed",children:y.email})]}),e.jsx(a.Td,{children:e.jsx(Es,{href:`https://${y.domain}`,target:"_blank",rel:"noopener noreferrer",size:"sm",children:y.domain})}),e.jsx(a.Td,{children:e.jsx(f,{color:y.action==="block"?"red":"gray",variant:"light",children:y.action})}),e.jsx(a.Td,{children:e.jsx(r,{size:"sm",children:y.nodeHostname||"—"})})]},y.id))})]}),q>1&&e.jsx(i,{justify:"center",mt:"md",children:e.jsx(xs,{value:u,onChange:S,total:q})})]}
3):e.jsx(ie,{color:"gray",icon:e.jsx(Ae,{size:16}),children:"Нет данных"})]})}const gs=30,_e={pending:{label:"Ожидает оплаты",color:"gray"},awaiting_review:{label:"На проверке",color:"yellow"},paid:{label:"Оплачен",color:"green"},cancelled:{label:"Отменён",color:"red"},expired:{label:"Просрочен",color:"orange"}},Hr=[{value:"",label:"Все статусы"},{value:"pending",label:_e.pending.label},{value:"awaiting_review",label:_e.awaiting_review.label},{value:"paid",label:_e.paid.label},{value:"cancelled",label:_e.cancelled.label},{value:"expired",label:_e.expired.label}],qs={pending:{label:"Ожидает проверки",color:"yellow"},approved:{label:"Одобрен",color:"green"},rejected:{label:"Отклонён",color:"red"}};function Hs(c){const k=typeof c=="string"?Number(c):c;return isFinite(k)?(k/100).toLocaleString("ru-RU",{style:"currency",currency:"RUB",maximumFractionDigits:2}):"—"}function ns(c){return c?oe(c).format("DD.MM.YYYY HH:mm"):"—"}function _r(c){return c?oe(c).format("DD.MM.YYYY"):"—"}function Vr(c){return c==null?"Без НДС":c===0?"НДС 0%":`НДС ${c}%`}function ls(c){if(!c||typeof c!="string")return null;const k=c.trim();return/^https?:\/\//i.test(k)?k.replace(/(["'()\\])/g,"\\$1").replace(/\s/g,"%20"):null}function Yr(){const{token:c}=Re(),[k,N]=n.useState(!1),[$,F]=n.useState([]),[g,D]=n.useState(0),[h,d]=n.useState(1),[u,S]=n.useState(""),[A,z]=n.useState(""),[T,M]=n.useState([]),[q,C]=n.useState(null),[H,U]=n.useState(!1),[x,E]=n.useState(Gr()),[y,K]=n.useState(!1),[w,ee]=n.useState({organizationId:"",amountRub:0,vatRate:"",periodMonths:1,description:"",dueAt:""}),[V,L]=n.useState(!1),[be,ve]=n.useState(!1),[ce,Y]=n.useState(null),[re,s]=n.useState(null),o=async()=>{N(!0);try{const t=new URLSearchParams;t.set("limit",String(gs)),t.set("offset",String((h-1)*gs)),u&&t.set("status",u),A&&t.set("organizationId",A);const j=await fetch(`/api/admin/corporate/invoices?${t.toString()}`,{headers:{Authorization:`Bearer ${c}`}});if(!j.ok)throw new Error("Не удалось загрузить счета");const R=await j.json();F(R.items),D(R.total)}catch(t){p.show({title:"Ошибка",message:t.message,color:"red"})}finally{N(!1)}},P=async()=>{try{const t=await fetch("/api/admin/corporate/organizations",{headers:{Authorization:`Bearer ${c}`}});if(!t.ok)return;const j=await t.json();M((Array.isArray(j)?j:j.items||[]).map(R=>({id:String(R.id),name:R.name})))}catch{}},G=async()=>{try{const t=await fetch("/api/admin/corporate/invoices/bank-details",{headers:{Authorization:`Bearer ${c}`}});if(!t.ok)return;const j=await t.json();C(j.bankDetails),j.bankDetails&&E(j.bankDetails)}catch{}};n.useEffect(()=>{P(),G()},[]),n.useEffect(()=>{o()},[h,u,A]);const X=async()=>{U(!0);try{const t=await fetch("/api/admin/corporate/invoices/bank-details",{method:"POST",headers:{Authorization:`Bearer ${c}`,"Content-Type":"application/json"},body:JSON.stringify(x)});if(!t.ok){const R=await t.json().catch(()=>({}));throw new Error(R?.message||"Не удалось сохранить реквизиты")}const j=await t.json();C(j.bankDetails),p.show({title:"Реквизиты сохранены",message:"Будут использованы во всех новых счетах",color:"green"})}catch(t){p.show({title:"Ошибка",message:t.message,color:"red"})}finally{U(!1)}},Ne=async()=>{if(!w.organizationId){p.show({title:"Не выбрана организация",message:"Выберите организацию из списка",color:"red"});return}if(!w.amountRub||w.amountRub<=0){p.show({title:"Некорректная сумма",message:"Сумма должна быть больше 0",color:"red"});return}if(w.vatRate===""){p.show({title:"Не выбрана ставка НДС",message:"Укажите «Без НДС» или ставку 0/10/20%",color:"red"});return}const t=w.vatRate==="none"?null:Number(w.vatRate);try{const j=await fetch(`/api/admin/corporate/organizations/${w.organizationId}/invoices`,{method:"POST",headers:{Authorization:`Bearer ${c}`,"Content-Type":"application/json"},body:JSON.stringify({amountCents:Math.round(w.amountRub*100),vatRate:t,periodMonths:w.periodMonths,description:w.description||void 0,dueAt:w.dueAt||void 0})});if(!j.ok){const R=await j.json().catch(()=>({}));throw new Error(R?.message||"Не удалось создать счёт")}p.show({title:"Счёт создан",message:"Клиент увидит его в портале",color:"green"}),K(!1),ee({organizationId:"",amountRub:0,vatRate:"",periodMonths:1,description:"",dueAt:""}),await o()}catch(j){p.show({title:"Ошибка",message:j.message,color:"red"})}},pe=async(t,j)=>{const R=t==="signatureImageUrl"?L:ve;R(!0);try{const ye=new FormData;ye.append("file",j);const l=await fetch("/api/upload/corp-signature",{method:"POST",headers:{Authorization:`Bearer ${c}`},body:ye});if(!l.ok){const se=await l.json().catch(()=>({}));throw new Error(se?.message||"Не удалось загрузить файл")}const I=await l.json();E(se=>({...se,[t]:I.url})),p.show({title:"Файл загружен",message:t==="signatureImageUrl"?"Факсимиле обновлено — не забудьте «Сохранить реквизиты»":"Печать обновлена — не забудьте «Сохранить реквизиты»",color:"green"})}catch(ye){p.show({title:"Ошибка",message:ye.message,color:"red"})}finally{R(!1)}},m=async t=>{try{const j=await fetch(`/api/admin/corporate/invoices/payments/${t}/approve`,{method:"POST",headers:{Authorization:`Bearer ${c}`}});if(!j.ok){const ye=await j.json().catch(()=>({}));throw new Error(ye?.message||"Не удалось одобрить")}const R=await j.json();p.show({title:"Платёж одобрен",message:`Подписка продлена до ${oe(R.newExpiresAt).format("DD.MM.YYYY")}`,color:"green"}),await o()}catch(j){p.show({title:"Ошибка",message:j.message,color:"red"})}},W=async()=>
3{if(ce){if(!ce.reason.trim()){p.show({title:"Укажите причину",message:"Причина обязательна для отклонения",color:"red"});return}try{const t=await fetch(`/api/admin/corporate/invoices/payments/${ce.paymentId}/reject`,{method:"POST",headers:{Authorization:`Bearer ${c}`,"Content-Type":"application/json"},body:JSON.stringify({reason:ce.reason.trim()})});if(!t.ok){const j=await t.json().catch(()=>({}));throw new Error(j?.message||"Не удалось отклонить")}p.show({title:"Платёж отклонён",message:"Клиент увидит причину в портале",color:"orange"}),Y(null),await o()}catch(t){p.show({title:"Ошибка",message:t.message,color:"red"})}}},te=async(t,j)=>{await Le(`/api/admin/corporate/invoices/${t}/pdf`,`${j}.pdf`)},ge=async(t,j)=>{await Le(`/api/admin/corporate/invoices/${t}/upd`,`UPD-${j}.pdf`)},Le=async(t,j)=>{try{const R=await fetch(t,{headers:{Authorization:`Bearer ${c}`}});if(!R.ok){const se=await R.json().catch(()=>({}));throw new Error(se?.message||`HTTP ${R.status}`)}const ye=await R.blob(),l=URL.createObjectURL(ye),I=document.createElement("a");I.href=l,I.download=j,document.body.appendChild(I),I.click(),I.remove(),setTimeout(()=>URL.revokeObjectURL(l),1e3)}catch(R){p.show({title:"Ошибка",message:R?.message||"Не удалось скачать PDF",color:"red"})}},Oe=async()=>{if(re)try{const t=await fetch(`/api/admin/corporate/invoices/${re.invoiceId}/cancel`,{method:"POST",headers:{Authorization:`Bearer ${c}`,"Content-Type":"application/json"},body:JSON.stringify({reason:re.reason.trim()||void 0})});if(!t.ok){const j=await t.json().catch(()=>({}));throw new Error(j?.message||"Не удалось отменить счёт")}p.show({title:"Счёт отменён",message:"Клиент больше не сможет оплатить",color:"orange"}),s(null),await o()}catch(t){p.show({title:"Ошибка",message:t.message,color:"red"})}},fe=n.useMemo(()=>T.map(t=>({value:t.id,label:`${t.name} (id ${t.id})`})),[T]),Fe=Math.max(1,Math.ceil(g/gs));return e.jsxs(B,{gap:"lg",children:[e.jsxs(O,{p:"md",withBorder:!0,children:[e.jsxs(i,{gap:"xs",mb:"md",children:[e.jsx(zr,{size:18}),e.jsx(ke,{order:4,children:"Реквизиты EOFVPN"})]}),e.jsx(r,{size:"sm",c:"dimmed",mb:"md",children:"Реквизиты, которые автоматически подставятся в новые счета. Уже выставленные счета сохраняют свою копию реквизитов и не изменяются."}),e.jsxs(xe,{children:[e.jsx(xe.Col,{span:{base:12,sm:6},children:e.jsx(_,{label:"Получатель",required:!0,value:x.recipientName,onChange:t=>E({...x,recipientName:t.currentTarget.value})})}),e.jsx(xe.Col,{span:{base:6,sm:3},children:e.jsx(_,{label:"ИНН",value:x.inn||"",onChange:t=>E({...x,inn:t.currentTarget.value})})}),e.jsx(xe.Col,{span:{base:6,sm:3},children:e.jsx(_,{label:"КПП",value:x.kpp||"",onChange:t=>E({...x,kpp:t.currentTarget.value})})}),e.jsx(xe.Col,{span:{base:12,sm:6},children:e.jsx(_,{label:"Банк",required:!0,value:x.bankName,onChange:t=>E({...x,bankName:t.currentTarget.value})})}),e.jsx(xe.Col,{span:{base:6,sm:3},children:e.jsx(_,{label:"БИК",required:!0,value:x.bic,onChange:t=>E({...x,bic:t.currentTarget.value})})}),e.jsx(xe.Col,{span:{base:12,sm:6},children:e.jsx(_,{label:"Расчётный счёт",required:!0,value:x.account,onChange:t=>E({...x,account:t.currentTarget.value})})}),e.jsx(xe.Col,{span:{base:12,sm:6},children:e.jsx(_,{label:"Корр. счёт",value:x.corrAccount||"",onChange:t=>E({...x,corrAccount:t.currentTarget.value})})}),e.jsx(xe.Col,{span:12,children:e.jsx(Ce,{label:"Назначение платежа (по умолчанию)",minRows:2,value:x.paymentPurpose||"",onChange:t=>E({...x,paymentPurpose:t.currentTarget.value})})}),e.jsx(xe.Col,{span:12,children:e.jsx(he,{label:e.jsxs(i,{gap:6,children:[e.jsx(Ns,{size:14}),e.jsx(r,{size:"sm",fw:600,children:"Подпись и печать для УПД / актов"})]}),labelPosition:"left",my:4})}),e.jsx(xe.Col,{span:{base:12,sm:4},children:e.jsx(_,{label:"ФИО руководителя",placeholder:"Иванов И.И.",value:x.signatoryName||"",onChange:t=>E({...x,signatoryName:t.currentTarget.value})})}),e.jsx(xe.Col,{span:{base:12,sm:4},children:e.jsx(_,{label:"Должность",placeholder:"Генеральный директор",value:x.signatoryPosition||"",onChange:t=>E({...x,signatoryPosition:t.currentTarget.value})})}),e.jsx(xe.Col,{span:{base:12,sm:4},children:e.jsx(_,{label:"ФИО главного бухгалтера",placeholder:"оставьте пустым = тот же",value:x.accountantName||"",onChange:t=>E({...x,accountantName:t.currentTarget.value})})}),e.jsx(xe.Col,{span:{base:12,sm:6},children:e.jsxs(B,{gap:6,children:[e.jsx(r,{size:"sm",fw:500,children:"Факсимиле подписи (PNG/JPG, до 2 МБ)"}),e.jsxs(i,{gap:"xs",align:"center",wrap:"nowrap",children:[ls(x.signatureImageUrl)?e.jsx(Ee,{style:{width:120,height:50,backgroundImage:`url('${ls(x.signatureImageUrl)}')`,backgroundSize:"contain",backgroundRepeat:"no-repeat",backgroundPosition:"center",border:"1px solid var(--mantine-color-default-border)",borderRadius:4}}):e.jsx(r,{size:"xs",c:"dimmed",children:"Не загружено"}),e.jsx(v,{size:"xs",variant:"default",leftSection:e.jsx(Fs,{size:14}),loading:V,onClick:()=>{const t=document.createElement("input");t.type="file",t.accept="image/png,image/jpeg,image/webp",t.onchange=j=>{const R=j.target.files?.[0];R&&pe("signatureImageUrl",R)},t.click()},children:x.signatureImageUrl?"Заменить":"Загрузить"}),x.signatureImageUrl&&e.jsx(v,{size:"xs",variant:"subtle",color:"red",leftSection:e.jsx(Be,{size:14}),onClick:()=>E({...x,signatureImageUrl:""}),children:"Удалить"})]})]})}),e.jsx(xe.Col,{span:{base:12,sm:6},children:e.jsxs(B,{gap:6,children:[e.jsx(r,{size:"sm",fw:500,children:"Печать (PNG/JPG, до 2 МБ)"}),e.jsxs(i,{gap:"xs",align:"center",wrap:"nowrap",children:[ls(x.stampImageUrl)?e.jsx(Ee,{style:{width:60,height:60,backgroundImage:`url('${ls(x.stampImageUrl)}')`,backgroundSize:"contain",backgroundRepeat:"no-repeat",backgroundPosition:"center",border:"1px solid var(--mantine-color-default-border)",borderRadius:4}}):e.jsx(r,{size:"xs",c:"dimmed",children:"Не загружена"}),e.jsx(v,{size:"xs",variant:"default",leftSection:e.jsx(Fs,{size:14}),loading:be,onClick:()=>{const t=document.createElement("input");t.type="file",t.accept="image/png,image/jpeg,image/webp",t.onchange=j=>{const R=j.target.files?.[0];R&&pe("stampImageUrl",R)},t.click()},children:x.stampImageUrl?"Заменить":"Загрузить"}),x.stampImageUrl&&e.jsx(v,{size:"xs",variant:"subtle",color:"red",leftSection:e.jsx(Be,{size:14}),onClick:()=>E({...x,stampImageUrl:""}),children:"Удалить"})]})]})})]}),e.jsx(i,{justify:"flex-end",mt:"md",children:e.jsx(v,{onClick:X,loading:H,leftSection:e.jsx(we,{size:16}),children:"Сохранить реквизиты"})})]}),e.jsxs(O,{p:"md",withBorder:!0,children:[e.jsxs(i,{justify:"space-between",mb:"md",children:[e.jsxs(i,{gap:"xs",children:[e.jsx(Xs,{size:20}),e.jsx(ke,{order:4,children:"Счета корпоративным клиентам"})]}),e.jsxs(i,{children:[e.jsx(v,{variant:"default",leftSection:e.jsx(De,{size:16}),onClick:()=>o(),children:"Обновить"}),e.jsx(v,{leftSection:e.jsx(es,{size:16}),onClick:()=>K(!0),disabled:!q,children:"Выставить счёт"})]})]}
3),!q&&e.jsx(ie,{color:"yellow",icon:e.jsx(Ae,{}),mb:"md",children:"Сначала сохраните реквизиты EOFVPN — без них нельзя создать счёт."}),e.jsxs(i,{mb:"md",gap:"sm",children:[e.jsx(Te,{placeholder:"Все организации",data:[{value:"",label:"Все организации"},...fe],value:A,onChange:t=>{z(t??""),d(1)},clearable:!0,searchable:!0,w:280}),e.jsx(Te,{data:Hr,value:u,onChange:t=>{S(t??""),d(1)},w:200})]}),k?e.jsx($e,{py:"xl",children:e.jsx(Pe,{})}):$.length===0?e.jsx(r,{c:"dimmed",ta:"center",py:"xl",children:"Счетов не найдено"}):e.jsx(is,{variant:"separated",children:$.map(t=>e.jsxs(is.Item,{value:t.id,children:[e.jsxs(i,{wrap:"nowrap",gap:"xs",align:"center",pr:"sm",children:[e.jsx(Ee,{style:{flex:1,minWidth:0},children:e.jsx(is.Control,{children:e.jsxs(i,{justify:"space-between",wrap:"nowrap",gap:"md",children:[e.jsxs(i,{gap:"sm",wrap:"nowrap",children:[e.jsx(r,{fw:600,children:t.invoiceNumber}),e.jsx(f,{color:_e[t.status].color,children:_e[t.status].label}),e.jsx(f,{color:t.vatRate==null?"gray":"blue",variant:"light",children:Vr(t.vatRate)})]}),e.jsxs(i,{gap:"lg",wrap:"nowrap",children:[e.jsx(r,{size:"sm",c:"dimmed",lineClamp:1,children:t.organizationName??`org ${t.organizationId}`}),e.jsx(r,{fw:600,children:Hs(t.amountCents)}),e.jsxs(r,{size:"sm",c:"dimmed",children:["+",t.periodMonths," мес"]})]})]})})}),e.jsx(Z,{label:"Скачать PDF счёта",children:e.jsx(v,{size:"xs",variant:"light",leftSection:e.jsx(Er,{size:14}),onClick:j=>{j.stopPropagation(),te(t.id,t.invoiceNumber)},children:"PDF"})}),t.status==="paid"&&e.jsx(Z,{label:"Скачать УПД (закрывающий документ)",children:e.jsx(v,{size:"xs",variant:"light",color:"violet",leftSection:e.jsx(Ns,{size:14}),onClick:j=>{j.stopPropagation(),ge(t.id,t.invoiceNumber)},children:"УПД"})})]}),e.jsx(is.Panel,{children:e.jsxs(B,{gap:"xs",children:[e.jsxs(i,{gap:"lg",children:[e.jsxs(r,{size:"sm",children:[e.jsx("b",{children:"ИНН:"})," ",t.organizationInn||"—"]}),e.jsxs(r,{size:"sm",children:[e.jsx("b",{children:"Создан:"})," ",ns(t.createdAt)]}),e.jsxs(r,{size:"sm",children:[e.jsx("b",{children:"Срок:"})," ",ns(t.dueAt)]}),e.jsxs(r,{size:"sm",children:[e.jsx("b",{children:"Оплачен:"})," ",ns(t.paidAt)]})]}),t.description&&e.jsxs(r,{size:"sm",children:[e.jsx("b",{children:"Описание:"})," ",t.description]}),t.cancelReason&&e.jsxs(ie,{color:"red",icon:e.jsx(Os,{}),children:["Отменён: ",t.cancelReason]}),e.jsx(he,{label:"Платежи",labelPosition:"left",my:"xs"}),t.payments.length===0?e.jsx(r,{c:"dimmed",size:"sm",children:"Платежей пока нет"}):e.jsxs(a,{striped:!0,withTableBorder:!0,children:[e.jsx(a.Thead,{children:e.jsxs(a.Tr,{children:[e.jsx(a.Th,{children:"Дата отправки"}),e.jsx(a.Th,{children:"Сумма"}),e.jsx(a.Th,{children:"Дата платежа"}),e.jsx(a.Th,{children:"Файл"}),e.jsx(a.Th,{children:"Комментарий"}),e.jsx(a.Th,{children:"Статус"}),e.jsx(a.Th,{children:"Действия"})]})}),e.jsx(a.Tbody,{children:t.payments.map(j=>e.jsxs(a.Tr,{children:[e.jsx(a.Td,{children:ns(j.createdAt)}),e.jsx(a.Td,{children:Hs(j.amountCents)}),e.jsx(a.Td,{children:_r(j.paidAtClient)}),e.jsx(a.Td,{children:e.jsx(Es,{href:j.proofPath,target:"_blank",rel:"noopener noreferrer",size:"sm",children:e.jsxs(i,{gap:4,children:[j.proofFilename,e.jsx(Js,{size:12})]})})}),e.jsx(a.Td,{children:e.jsx(r,{size:"sm",lineClamp:2,children:j.note||"—"})}),e.jsxs(a.Td,{children:[e.jsx(f,{color:qs[j.status].color,children:qs[j.status].label}),j.rejectReason&&e.jsx(r,{size:"xs",c:"dimmed",mt:4,children:j.rejectReason})]}),e.jsx(a.Td,{children:j.status==="pending"?e.jsxs(i,{gap:"xs",wrap:"nowrap",children:[e.jsx(Z,{label:"Одобрить и продлить",children:e.jsx(v,{size:"xs",color:"green",leftSection:e.jsx(we,{size:14}),onClick:()=>m(j.id),children:"Одобрить"})}),e.jsx(Z,{label:"Отклонить с причиной",children:e.jsx(v,{size:"xs",color:"red",variant:"default",leftSection:e.jsx(Ps,{size:14}),onClick:()=>Y({paymentId:j.id,reason:""}),children:"Отклонить"})})]}):"—"})]},j.id))})]}),(t.status==="pending"||t.status==="awaiting_review"||t.status==="expired")&&e.jsx(i,{justify:"flex-end",mt:"sm",children:e.jsx(v,{variant:"default",color:"red",size:"xs",leftSection:e.jsx(Os,{size:14}),onClick:()=>s({invoiceId:t.id,reason:""}),children:"Отменить счёт"})})]})})]},t.id))}),Fe>1&&e.jsx(i,{justify:"center",mt:"md",children:e.jsx(xs,{value:h,onChange:d,total:Fe})})]}),e.jsx(Se,{opened:y,onClose:()=>K(!1),title:"Выставить счёт",size:"lg",children:e.jsxs(B,{gap:"md",children:[e.jsx(Te,{label:"Организация",placeholder:"Выберите...",data:fe,searchable:!0,required:!0,value:w.organizationId,onChange:t=>ee({...w,organizationId:t??""})}),e.jsxs(xe,{children:[e.jsx(xe.Col,{span:6,children:e.jsx(ze,{label:"Сумма, ₽ (включая НДС)",required:!0,min:1,max:1e7,decimalScale:2,fixedDecimalScale:!0,thousandSeparator:" ",value:w.amountRub,onChange:t=>ee({...w,amountRub:typeof t=="number"?t:Number(t)||0})})}),e.jsx(xe.Col,{span:6,children:e.jsx(ze,{label:"Продление, мес",required:!0,min:1,max:60,value:w.peri
3odMonths,onChange:t=>ee({...w,periodMonths:typeof t=="number"?t:1})})}),e.jsxs(xe.Col,{span:12,children:[e.jsx(Te,{label:"НДС",placeholder:"Выберите ставку",required:!0,description:"Обязательный выбор. Сумма выше — итоговая, включает НДС.",data:[{value:"none",label:"Без НДС (УСН)"},{value:"0",label:"НДС 0% (экспорт)"},{value:"10",label:"НДС 10%"},{value:"20",label:"НДС 20%"}],value:w.vatRate===""?null:w.vatRate,onChange:t=>ee({...w,vatRate:t??""})}),w.vatRate&&w.vatRate!=="none"&&w.amountRub>0&&e.jsx(r,{size:"xs",c:"dimmed",mt:4,children:(()=>{const t=Number(w.vatRate);if(t===0)return`НДС 0%: 0,00 ₽. Сумма без НДС: ${w.amountRub.toFixed(2)} ₽.`;const j=Math.round(w.amountRub*100),R=Math.round(j*t/(100+t)),ye=j-R;return`В т.ч. НДС ${t}%: ${(R/100).toFixed(2)} ₽. Сумма без НДС: ${(ye/100).toFixed(2)} ₽.`})()})]})]}),e.jsx(_,{label:"Срок оплаты",description:"ISO дата, например 2026-12-31 (опционально)",value:w.dueAt,onChange:t=>ee({...w,dueAt:t.currentTarget.value})}),e.jsx(Ce,{label:"Описание",placeholder:"Что включено в этот счёт (видно клиенту)",minRows:3,value:w.description,onChange:t=>ee({...w,description:t.currentTarget.value})}),e.jsxs(i,{justify:"flex-end",children:[e.jsx(v,{variant:"default",onClick:()=>K(!1),children:"Отмена"}),e.jsx(v,{onClick:Ne,children:"Выставить"})]})]})}),e.jsx(Se,{opened:ce!==null,onClose:()=>Y(null),title:"Отклонить платёж",size:"md",children:e.jsxs(B,{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Клиент увидит причину отклонения и сможет повторно отправить подтверждение."}),e.jsx(Ce,{label:"Причина",required:!0,minRows:3,value:ce?.reason||"",onChange:t=>{const j=t.currentTarget.value;Y(R=>R&&{...R,reason:j})}}),e.jsxs(i,{justify:"flex-end",children:[e.jsx(v,{variant:"default",onClick:()=>Y(null),children:"Отмена"}),e.jsx(v,{color:"red",onClick:W,children:"Отклонить"})]})]})}),e.jsx(Se,{opened:re!==null,onClose:()=>s(null),title:"Отменить счёт?",size:"md",children:e.jsxs(B,{children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Все ожидающие платежи по этому счёту будут автоматически отклонены."}),e.jsx(Ce,{label:"Причина (опционально)",minRows:2,value:re?.reason||"",onChange:t=>{const j=t.currentTarget.value;s(R=>R&&{...R,reason:j})}}),e.jsxs(i,{justify:"flex-end",children:[e.jsx(v,{variant:"default",onClick:()=>s(null),children:"Назад"}),e.jsx(v,{color:"red",onClick:Oe,children:"Отменить счёт"})]})]})})]})}function Gr(){return{recipientName:"",inn:"",kpp:"",bankName:"",bic:"",account:"",corrAccount:"",paymentPurpose:""}}const Wr=c=>{switch(c){case"completed":return"teal";case"failed":return"red";case"queued":return"blue";case"preview":return"gray";default:return"gray"}},Jr=c=>{switch(c){case"completed":return"Доставлено";case"failed":return"Ошибка";case"queued":return"В процессе";case"preview":return"Предпросмотр";default:return c}},Qs=[{value:"AT",label:"🇦🇹 AT — Австрия"},{value:"AU",label:"🇦🇺 AU — Австралия"},{value:"BR",label:"🇧🇷 BR — Бразилия"},{value:"CA",label:"🇨🇦 CA — Канада"},{value:"CH",label:"🇨🇭 CH — Швейцария"},{value:"CZ",label:"🇨🇿 CZ — Чехия"},{value:"DE",label:"🇩🇪 DE — Германия"},{value:"ES",label:"🇪🇸 ES — Испания"},{value:"FI",label:"🇫🇮 FI — Финляндия"},{value:"FR",label:"🇫🇷 FR — Франция"},{value:"GB",label:"🇬🇧 GB — Великобритания"},{value:"HK",label:"🇭🇰 HK — Гонконг"},{value:"IT",label:"🇮🇹 IT — Италия"},{value:"JP",label:"🇯🇵 JP — Япония"},{value:"KZ",label:"🇰🇿 KZ — Казахстан"}
3,{value:"NL",label:"🇳🇱 NL — Нидерланды"},{value:"PL",label:"🇵🇱 PL — Польша"},{value:"RU",label:"🇷🇺 RU — Россия"},{value:"SG",label:"🇸🇬 SG — Сингапур"},{value:"TR",label:"🇹🇷 TR — Турция"},{value:"UA",label:"🇺🇦 UA — Украина"},{value:"US",label:"🇺🇸 US — США"}],Kr=Qs.map(({value:c,label:k})=>({value:c,label:k.replace(/^\S+\s+/,"")}));function Zr({option:c}){return e.jsxs(i,{gap:"sm",wrap:"nowrap",children:[e.jsx(cs,{countryCode:c.value,size:18}),e.jsx(r,{size:"sm",children:c.label})]})}function Xr({orgId:c}){const{token:k}=Re(),[N,$]=n.useState([]),[F,g]=n.useState(!0),[D,{open:h,close:d}]=Ve(!1),[u,S]=n.useState(!1),A=He({initialValues:{name:"",country:"DE",serverType:"wireguard",publicHost:"",wgPort:51820,sshHost:"",sshUser:"root",sshPort:22,sshPassword:"",maxPeers:5e3}}),z=async()=>{g(!0);try{const C=await fetch(`/api/admin/corporate/organizations/${c}/wireguard/servers`,{headers:{Authorization:`Bearer ${k}`}});C.ok&&$(await C.json())}catch(C){console.error("Failed to load org WG servers:",C)}finally{g(!1)}};n.useEffect(()=>{z()},[c]);const T=async C=>{const H=Qs.find(U=>U.value===C.country);if(!H){p.show({color:"red",title:"Ошибка",message:"Выберите страну"});return}S(!0);try{const U=H.label.replace(/^[^\s]+\s/,"").split(" — ")[1]||C.country,x=await fetch(`/api/admin/corporate/organizations/${c}/wireguard/servers`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${k}`},body:JSON.stringify({name:C.name,country:U,countryCode:C.country,serverType:C.serverType,publicHost:C.publicHost,wgPort:C.wgPort,sshHost:C.sshHost,sshUser:C.sshUser,sshPort:C.sshPort,sshPassword:C.sshPassword,maxPeers:C.maxPeers})});if(!x.ok){const E=await x.json().catch(()=>({}));throw new Error(E.message||"Не удалось создать сервер")}p.show({color:"green",title:"Сервер добавлен",message:"Запустите установку, чтобы поднять интерфейс.",icon:e.jsx(we,{size:16})}),d(),A.reset(),z()}catch(U){p.show({color:"red",title:"Ошибка",message:U.message||"Не удалось создать сервер"})}finally{S(!1)}},M=async(C,H)=>{try{const U=await fetch(`/api/admin/corporate/organizations/${c}/wireguard/servers/${C}/${H}`,{method:"POST",headers:{Authorization:`Bearer ${k}`}});if(!U.ok){const x=await U.json().catch(()=>({}));throw new Error(x.message||"Не удалось выполнить действие")}p.show({color:"green",title:"Готово",message:H}),z()}catch(U){p.show({color:"red",title:"Ошибка",message:U.message})}},q=async C=>{if(confirm("Удалить сервер? Все peers будут удалены."))try{const H=await fetch(`/api/admin/corporate/organizations/${c}/wireguard/servers/${C}`,{method:"DELETE",headers:{Authorization:`Bearer ${k}`}});if(!H.ok){const U=await H.json().catch(()=>({}));throw new Error(U.message||"Не удалось удалить сервер")}p.show({color:"green",title:"Удалено",message:"Сервер удалён"}),z()}catch(H){p.show({color:"red",title:"Ошибка",message:H.message})}};return F?e.jsx(i,{justify:"center",py:"md",children:e.jsx(Pe,{size:"sm"})}):e.jsxs(B,{gap:"sm",children:[e.jsxs(i,{justify:"space-between",children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Серверы привязаны к этой организации. Сотрудники получат конфиги внутри корп. портала, если в плане включены доп. протоколы."}),e.jsx(v,{size:"xs",leftSection:e.jsx(es,{size:14}),onClick:h,children:"Добавить сервер"})]}),N.length===0?e.jsx(ie,{color:"gray",variant:"light",icon:e.jsx(Is,{size:16}),children:"Серверов пока нет. Добавьте WireGuard или AmneziaWG-сервер и запустите установку — это поднимет интерфейс на удалённом VPS по SSH."}):e.jsx(B,{gap:"xs",children:N.map(C=>
3e.jsx(O,{p:"sm",radius:"md",withBorder:!0,children:e.jsxs(i,{justify:"space-between",wrap:"nowrap",children:[e.jsxs(i,{gap:"sm",wrap:"nowrap",children:[e.jsx(ue,{size:"lg",radius:"md",variant:"light",color:C.serverType==="amneziawg"?"grape":"blue",children:e.jsx(ms,{size:18})}),e.jsxs("div",{children:[e.jsxs(i,{gap:6,wrap:"nowrap",children:[e.jsx(r,{fw:600,children:C.name}),e.jsx(cs,{countryCode:C.countryCode,size:18}),e.jsx(f,{size:"xs",variant:"light",color:"gray",children:C.countryCode}),e.jsx(f,{size:"xs",variant:"light",color:C.serverType==="amneziawg"?"grape":"blue",children:C.serverType==="amneziawg"?"AmneziaWG":"WireGuard"}),e.jsx(f,{size:"xs",variant:"light",color:C.status==="active"?"teal":C.status==="error"?"red":"yellow",children:C.status})]}),e.jsxs(r,{size:"xs",c:"dimmed",children:[C.publicHost,":",C.wgPort," · peers ",C.currentPeers,"/",C.maxPeers]})]})]}),e.jsxs(i,{gap:4,children:[e.jsx(Z,{label:"Установить / переустановить",children:e.jsx(le,{variant:"light",color:"blue",onClick:()=>M(C.id,"install"),children:e.jsx(vs,{size:16})})}),e.jsx(Z,{label:"Применить конфиг",children:e.jsx(le,{variant:"light",color:"cyan",onClick:()=>M(C.id,"apply-config"),children:e.jsx(kr,{size:16})})}),e.jsx(Z,{label:"Удалить",children:e.jsx(le,{variant:"light",color:"red",onClick:()=>q(C.id),children:e.jsx(Be,{size:16})})})]})]})},C.id))}),e.jsx(Se,{opened:D,onClose:d,title:"Добавить WG/AmneziaWG-сервер",size:"lg",children:e.jsx("form",{onSubmit:A.onSubmit(T),children:e.jsxs(B,{gap:"sm",children:[e.jsxs(Q,{cols:{base:1,sm:2},children:[e.jsx(_,{label:"Название",required:!0,...A.getInputProps("name")}),e.jsx(Te,{label:"Страна",required:!0,data:Kr,renderOption:Zr,leftSection:e.jsx(cs,{countryCode:A.values.country,size:18}),searchable:!0,...A.getInputProps("country")})]}),e.jsxs(Q,{cols:{base:1,sm:2},children:[e.jsx(Te,{label:"Тип сервера",data:[{value:"wireguard",label:"WireGuard"},{value:"amneziawg",label:"AmneziaWG (с обфускацией)"}],...A.getInputProps("serverType")}),e.jsx(ze,{label:"Макс. peer'ов",min:1,max:1e4,...A.getInputProps("maxPeers")})]}),e.jsx(he,{label:"Подключение клиентов"}),e.jsxs(Q,{cols:{base:1,sm:2},children:[e.jsx(_,{label:"Публичный хост",description:"IP или домен, к которому подключаются peers",required:!0,...A.getInputProps("publicHost")}),e.jsx(ze,{label:"WG порт",min:1,max:65535,...A.getInputProps("wgPort")})]}),e.jsx(he,{label:"SSH доступ для установки"}),e.jsxs(Q,{cols:{base:1,sm:2},children:[e.jsx(_,{label:"SSH host",description:"Может совпадать с публичным хостом",required:!0,...A.getInputProps("sshHost")}),e.jsx(ze,{label:"SSH port",min:1,max:65535,...A.getInputProps("sshPort")})]}),e.jsxs(Q,{cols:{base:1,sm:2},children:[e.jsx(_,{label:"SSH user",required:!0,...A.getInputProps("sshUser")}),e.jsx(As,{label:"SSH password",required:!0,...A.getInputProps("sshPassword")})]}),e.jsxs(i,{justify:"flex-end",mt:"md",children:[e.jsx(v,{variant:"subtle",onClick:d,children:"Отмена"}),e.jsx(v,{type:"submit",loading:u,children:"Создать"})]})]})})})]})}function Qr({orgId:c}){const{token:k}=Re(),[N,$]=n.useState(null),[F,g]=n.useState(!0),D=async()=>{g(!0);try{const z=await fetch(`/api/admin/corporate/organizations/${c}/bot`,{headers:{Authorization:`Bearer ${k}`}});z.ok&&$(await z.json())}catch(z){console.error("Failed to load org bot info:",z)}finally{g(!1)}};if(n.useEffect(()=>{D()},[c]),F)return e.jsx(i,{justify:"center",py:"md",children:e.jsx(Pe,{size:"sm"})});if(!N)return null;const{bot:h,stats:d,broadcasts:u,invites:S}=N,A=d.totalMembers?Math.round(d.linkedMembers/d.totalMembers*100):0;return e.jsxs(B,{gap:"md",children:[h?e.jsxs(e.Fragment,{children:[e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsxs(i,{justify:"space-between",wrap:"nowrap",mb:"sm",children:[e.jsxs(i,{gap:"sm",wrap:"nowrap",children:[e.jsx(ue,{size:"lg",radius:"xl",color:"cyan",variant:"light",children:e.jsx(hs,{size:18})}),e.jsxs("div",{children:[e.jsxs(i,{gap:6,wrap:"nowrap",children:[e.jsx(r,{fw:600,children:h.botUsername?`@${h.botUsername}`:"Бот без username"}),e.jsx(f,{size:"xs",variant:"light",color:h.isEnabled?"teal":"gray",children:h.isEnabled?"Включён":"Выключен"}),h.webhookSetAt?e.jsx(f,{size:"xs",variant:"light",color:"teal",leftSection:e.jsx(ur,{size:10}),children:"webhook"}):e.jsx(f,{size:"xs",variant:"light",color:"yellow",children:"webhook не установлен"})]}),e.jsxs(r,{size:"xs",c:"dimmed",children:[h.botName||"—"," · подключён ",oe(h.createdAt).format("DD.MM.YYYY HH:mm")]})]})]}),e.jsx(Z,{label:"Обновить данные",children:e.jsx(le,{variant:"subtle",onClick:D,children:e.jsx(De,{size:14})})})]}),h.webhookLastError&&e.jsxs(ie,{variant:"light",color:"red",mt:"xs",mb:"xs",children:["Webhook: ",h.webhookLastError]}),e.jsxs(Q,{cols:{base:2,sm:4},spacing:"xs",children:[e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Привязали бота"}),e.jsxs(r,{fw:600,size:"sm",children:[d.linkedMembers," / ",d.totalMembers," ",e.jsxs(r,{component:"span",size:"xs",c:"dimmed",children:["(",A,"%)"]})]})]}),e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Сообщений принято"}
3),e.jsx(r,{fw:600,size:"sm",children:h.messagesIn.toLocaleString("ru-RU")})]}),e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Сообщений отправлено"}),e.jsx(r,{fw:600,size:"sm",children:h.messagesOut.toLocaleString("ru-RU")})]}),e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Последний update"}),e.jsx(r,{fw:600,size:"sm",children:h.lastUpdateAt?oe(h.lastUpdateAt).format("DD.MM HH:mm"):"—"})]})]}),e.jsx(he,{my:"sm"}),e.jsxs(Q,{cols:{base:2,sm:4},spacing:"xs",children:[e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Алерт владельца"}),e.jsx(r,{fw:600,size:"sm",children:h.ownerChatId||"—"})]}),e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Новые сотрудники"}),e.jsx(f,{size:"xs",variant:"light",color:h.notifyNewMember?"teal":"gray",children:h.notifyNewMember?"вкл":"выкл"})]}),e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Истечение"}),e.jsx(f,{size:"xs",variant:"light",color:h.notifyExpiry?"teal":"gray",children:h.notifyExpiry?"вкл":"выкл"})]}),e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Оплата"}),e.jsx(f,{size:"xs",variant:"light",color:h.notifyPayment?"teal":"gray",children:h.notifyPayment?"вкл":"выкл"})]})]})]}),e.jsxs(Q,{cols:{base:2,sm:4}
3,spacing:"xs",children:[e.jsxs(O,{p:"sm",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Рассылок всего"}),e.jsx(r,{fw:700,size:"lg",children:d.totalBroadcasts})]}),e.jsxs(O,{p:"sm",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Получателей всего"}),e.jsx(r,{fw:700,size:"lg",children:d.totalRecipients})]}),e.jsxs(O,{p:"sm",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Доставлено"}),e.jsx(r,{fw:700,size:"lg",c:"teal",children:d.totalSent})]}),e.jsxs(O,{p:"sm",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Ошибок"}),e.jsx(r,{fw:700,size:"lg",c:d.totalFailed>0?"red":"gray",children:d.totalFailed})]})]})]}):e.jsx(ie,{color:"gray",variant:"light",icon:e.jsx(hs,{size:16}),children:"Бот не подключён. Владелец организации может подключить его в корпоративном портале на странице «Telegram бот»."}),e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsxs(i,{gap:6,mb:"xs",children:[e.jsx($s,{size:14}),e.jsx(r,{fw:600,size:"sm",children:"История рассылок"}),e.jsx(f,{size:"xs",variant:"light",color:"gray",children:u.length})]}),u.length===0?e.jsx(r,{size:"xs",c:"dimmed",children:"Рассылок ещё не было"}):e.jsx(Ze.Autosize,{mah:320,type:"auto",children:e.jsx(B,{gap:"xs",children:u.map(z=>e.jsxs(O,{p:"xs",radius:"sm",withBorder:!0,children:[e.jsxs(i,{justify:"space-between",gap:"xs",wrap:"nowrap",mb:4,children:[e.jsxs(i,{gap:6,wrap:"nowrap",children:[e.jsx(f,{size:"xs",variant:"light",color:Wr(z.status),children:Jr(z.status)}),e.jsx(r,{size:"xs",c:"dimmed",children:oe(z.startedAt).format("DD.MM.YYYY HH:mm")})]}),z.status!=="preview"&&e.jsxs(i,{gap:4,wrap:"nowrap",children:[e.jsx(Z,{label:"Доставлено / всего",children:e.jsxs(f,{size:"xs",variant:"light",color:"teal",leftSection:e.jsx(_s,{size:10}),children:[z.sentCount,"/",z.totalRecipients]})}),z.failedCount>0&&e.jsxs(f,{size:"xs",variant:"light",color:"red",children:["ошибок: ",z.failedCount]})]})]}),e.jsx(r,{size:"xs",lineClamp:3,style:{whiteSpace:"pre-wrap"},children:z.text}),z.errorMessage&&e.jsx(r,{size:"xs",c:"red",mt:4,children:z.errorMessage}),z.initiatedByEmail&&e.jsxs(r,{size:"xs",c:"dimmed",mt:4,children:["от ",z.initiatedByEmail]})]},z.id))})})]}),S.length>0&&e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsxs(i,{gap:6,mb:"xs",children:[e.jsx(Zs,{size:14}),e.jsx(r,{fw:600,size:"sm",children:"Последние приглашения"}),e.jsx(f,{size:"xs",variant:"light",color:"gray",children:S.length})]}),e.jsx(Ze.Autosize,{mah:200,type:"auto",children:e.jsx(B,{gap:6,children:S.map(z=>{const T=!z.usedAt&&new Date(z.expiresAt)<new Date;return e.jsxs(i,{gap:"xs",wrap:"nowrap",justify:"space-between",children:[e.jsx(r,{size:"xs",ff:"monospace",style:{wordBreak:"break-all"},children:z.token}),e.jsx(i,{gap:4,wrap:"nowrap",children:e.jsx(f,{size:"xs",variant:"light",color:z.usedAt?"teal":T?"gray":"blue",children:z.usedAt?`использовано ${oe(z.usedAt).format("DD.MM HH:mm")}`:T?"просрочено":`до ${oe(z.expiresAt).format("DD.MM HH:mm")}`})})]},z.id)})})})]})]})}function ei(){const{token:c}=Re(),[k,N]=n.useState(!0),[$,F]=n.useState(!1),[g,D]=n.useState([]),[h,d]=n.useState(null),[u,{open:S,close:A}]=Ve(!1),[z,T]=n.useState(!1),[M,q]=n.useState(null),[C,H]=n.useState(!1),[U,x]=n.useState([]),E=He({initialValues:{name:"",inn:"",ownerEmail:"",maxUsers:10,trafficLimit:"",squadName:"",isActive:!0,expiresAt:null,requestedServers:[]},validate:{name:s=>s?null:"Название обязательно",maxUsers:s=>s<1?"Минимум 1":null}});n.useEffect(()=>{K(),y()},[]);const y=async()=>{try{const s=await fetch("/api/admin/corporate/remnawave/squads",{headers:{Authorization:`Bearer ${c}`}});s.ok&&x(await s.json())}catch(s){console.error("Failed to load Remnawave squads:",s)}},K=async()=>{N(!0);try{const s=await fetch("/api/admin/corporate/organizations",{headers:{Authorization:`Bearer ${c}`}});s.ok&&D(await s.json())}catch(s){console.error("Failed to load organizations:",s)}finally{N(!1)}},w=async s=>{try{const o=await fetch(`/api/admin/corporate/organizations/${s}`,{headers:{Authorization:`Bearer ${c}`}});if(o.ok){const P=await o.json();d(P),E.setValues({name:P.name||"",inn:P.inn||"",ownerEmail:P.ownerEmail||"",maxUsers:P.maxUsers||10,trafficLim
3it:P.trafficLimit?String(Number(P.trafficLimit)/(1024*1024*1024)):"",squadName:P.squadName||"",isActive:P.isActive,expiresAt:P.expiresAt?new Date(P.expiresAt):null,requestedServers:Array.isArray(P.order?.requestedServers)?P.order.requestedServers.map(G=>G.toUpperCase()):[]}),T(!1),S()}}catch(o){console.error("Failed to load org detail:",o)}},ee=async s=>{if(h){F(!0);try{const o={name:s.name,inn:s.inn||null,ownerEmail:s.ownerEmail||null,maxUsers:s.maxUsers,trafficLimit:s.trafficLimit?String(Number(s.trafficLimit)*1024*1024*1024):null,squadName:s.squadName||null,isActive:s.isActive,expiresAt:s.expiresAt?s.expiresAt instanceof Date?s.expiresAt.toISOString():new Date(s.expiresAt).toISOString():null,requestedServers:Array.isArray(s.requestedServers)?s.requestedServers.map(X=>X.toUpperCase()):[]},P=await fetch(`/api/admin/corporate/organizations/${h.id}`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`},body:JSON.stringify(o)});if(!P.ok){const X=await P.json();throw new Error(X.message)}const G=await P.json();d(G),p.show({title:"Сохранено",message:`Организация "${s.name}" обновлена`,color:"green"}),T(!1),K()}catch(o){p.show({title:"Ошибка",message:o.message,color:"red"})}finally{F(!1)}}},V=async s=>{H(!0);try{const o=await fetch(`/api/admin/corporate/organizations/${s.id}`,{method:"DELETE",headers:{Authorization:`Bearer ${c}`}});if(!o.ok){const P=await o.json();throw new Error(P.message)}p.show({title:"Удалено",message:`Организация "${s.name}" удалена`,color:"green"}),q(null),A(),K()}catch(o){p.show({title:"Ошибка",message:o.message,color:"red"})}finally{H(!1)}},L=s=>s?`${(Number(s)/(1024*1024*1024)).toFixed(0)} GB`:"Безлимит",be=s=>s?oe(s).diff(oe(),"day"):null,ve={owner:"Владелец",admin:"Администратор",member:"Сотрудник"},ce={owner:"yellow",admin:"blue",member:"gray"};if(k)return e.jsx($e,{py:"xl",children:e.jsx(Pe,{})});const Y=g.filter(s=>s.isActive),re=g.filter(s=>!s.isActive);return e.jsxs(B,{gap:"lg",children:[e.jsxs(Q,{cols:{base:1,sm:3},spacing:"md",children:[e.jsx(O,{p:"md",radius:"md",withBorder:!0,children:e.jsxs(i,{children:[e.jsx(ue,{size:"lg",radius:"md",variant:"light",color:"green",children:e.jsx(Ie,{size:20})}),e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Активных"}),e.jsx(r,{size:"xl",fw:700,children:Y.length})]})]})}),e.jsx(O,{p:"md",radius:"md",withBorder:!0,children:e.jsxs(i,{children:[e.jsx(ue,{size:"lg",radius:"md",variant:"light",color:"gray",children:e.jsx(Ie,{size:20})}),e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Неактивных"}),e.jsx(r,{size:"xl",fw:700,children:re.length})]})]})}),e.jsx(O,{p:"md",radius:"md",withBorder:!0,children:e.jsxs(i,{children:[e.jsx(ue,{size:"lg",radius:"md",variant:"light",color:"blue",children:e.jsx(ss,{size:20})}),e.jsxs("div",{children:[e.jsx(r,{size:"xs",c:"dimmed",children:"Всего сотрудников"}),e.jsx(r,{size:"xl",fw:700,children:g.reduce((s,o)=>s+(o._count?.members||0),0)})]})]})})]}),Y.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs(i,{justify:"space-between",children:[e.jsx(ke,{order:4,children:"Активные корпорации"}),e.jsx(f,{color:"green",variant:"light",children:Y.length})]}),e.jsx(Q,{cols:{base:1,sm:2,lg:3},spacing:"md",children:Y.map(s=>{const o=be(s.expiresAt),P=s._count?.members?Math.min(s._count.members/s.maxUsers*100,100):0;return e.jsxs(je,{withBorder:!0,radius:"lg",padding:"lg",children:[e.jsxs(i,{justify:"space-between",mb:"md",children:[e.jsxs(i,{gap:"sm",children:[e.jsx(os,{color:"blue",radius:"xl",children:e.jsx(Ie,{size:20})}),e.jsxs("div",{children:[e.jsx(r,{fw:600,size:"lg",children:s.name}),e.jsx(r,{size:"xs",c:"dimmed",children:s.ownerEmail})]})]}),e.jsx(f,{color:"green",variant:"light",children:"Активна"})]}),e.jsxs(B,{gap:"xs",mb:"md",children:[e.jsxs(i,{justify:"space-between",children:[e.jsx(r,{size:"sm",c:"dimmed",children:"План"}),e.jsx(f,{variant:"outline",children:s.order?.plan?.name||"—"})]}),e.jsxs(i,{justify:"space-between",children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Сотрудников"}),e.jsxs(r,{size:"sm",fw:500,children:[s._count?.members||0," / ",s.maxUsers]})]}
3),e.jsx(cr,{value:P,size:"sm",radius:"xl",color:P>90?"red":P>70?"yellow":"blue"}),e.jsxs(i,{justify:"space-between",children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Трафик"}),e.jsx(r,{size:"sm",fw:500,children:L(s.trafficLimit)})]}),s.squadName&&e.jsxs(i,{justify:"space-between",children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Сквад"}),e.jsx(f,{size:"sm",variant:"dot",color:"violet",children:s.squadName})]}),o!==null&&e.jsxs(i,{justify:"space-between",children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Осталось"}),e.jsxs(f,{size:"sm",color:o>30?"green":o>7?"yellow":"red",children:[o," дней"]})]}),e.jsxs(i,{justify:"space-between",children:[e.jsx(r,{size:"sm",c:"dimmed",children:"Telegram-бот"}),s.bot?e.jsx(f,{size:"sm",variant:"light",color:s.bot.isEnabled&&s.bot.webhookActive?"cyan":"yellow",leftSection:e.jsx(hs,{size:10}),children:s.bot.botUsername?`@${s.bot.botUsername}`:"Подключён"}):e.jsx(f,{size:"sm",variant:"light",color:"gray",children:"Не подключён"})]})]}),e.jsxs(i,{gap:"xs",children:[e.jsx(Z,{label:"Подробнее",children:e.jsx(le,{variant:"light",onClick:()=>w(s.id),children:e.jsx(bs,{size:16})})}),e.jsx(Z,{label:"Редактировать",children:e.jsx(le,{variant:"light",color:"blue",onClick:()=>{w(s.id).then(()=>T(!0))},children:e.jsx(Ye,{size:16})})}),e.jsx(Z,{label:"Удалить",children:e.jsx(le,{variant:"light",color:"red",onClick:()=>q(s),children:e.jsx(Be,{size:16})})})]})]},s.id)})})]}),re.length>0&&e.jsxs(e.Fragment,{children:[e.jsx(he,{my:"md"}),e.jsxs(i,{justify:"space-between",children:[e.jsx(ke,{order:4,c:"dimmed",children:"Неактивные"}),e.jsx(f,{color:"gray",variant:"light",children:re.length})]}),e.jsx(Q,{cols:{base:1,sm:2,lg:3},spacing:"md",children:re.map(s=>e.jsxs(je,{withBorder:!0,radius:"lg",padding:"lg",style:{opacity:.7},children:[e.jsxs(i,{justify:"space-between",mb:"md",children:[e.jsxs(i,{gap:"sm",children:[e.jsx(os,{color:"gray",radius:"xl",children:e.jsx(Ie,{size:20})}),e.jsxs("div",{children:[e.jsx(r,{fw:600,children:s.name}),e.jsx(r,{size:"xs",c:"dimmed",children:s.ownerEmail})]})]}),e.jsx(f,{color:"gray",variant:"light",children:"Неактивна"})]}),e.jsxs(r,{size:"sm",c:"dimmed",mb:"md",children:["Создана: ",oe(s.createdAt).format("DD.MM.YYYY")]}),e.jsxs(i,{gap:"xs",children:[e.jsx(Z,{label:"Подробнее",children:e.jsx(le,{variant:"light",onClick:()=>w(s.id),children:e.jsx(bs,{size:16})})}),e.jsx(Z,{label:"Редактировать",children:e.jsx(le,{variant:"light",color:"blue",onClick:()=>{w(s.id).then(()=>T(!0))},children:e.jsx(Ye,{size:16})})}),e.jsx(Z,{label:"Удалить",children:e.jsx(le,{variant:"light",color:"red",onClick:()=>q(s),children:e.jsx(Be,{size:16})})})]})]},s.id))})]}),g.length===0&&e.jsxs(O,{p:"xl",radius:"lg",withBorder:!0,ta:"center",children:[e.jsx(ue,{size:64,radius:"xl",variant:"light",color:"gray",mx:"auto",mb:"md",children:e.jsx(Ie,{size:32})}),e.jsx(ke,{order:4,c:"dimmed",mb:"xs",children:"Нет корпораций"}),e.jsx(r,{c:"dimmed",children:"Корпорации появятся после активации заказов"})]}),e.jsxs(Se,{opened:u,onClose:()=>{A(),T(!1)},title:e.jsxs(i,{gap:"sm",children:[e.jsx(ue,{size:"lg",radius:"md",variant:"light",color:"blue",children:e.jsx(Ie,{size:20})}),e.jsxs("div",{children:[e.jsx(r,{fw:600,size:"lg",children:h?.name||"Организация"}),e.jsxs(r,{size:"xs",c:"dimmed",children:["ID: ",h?.id]})]})]}),size:"lg",centered:!0,children:[h&&!z&&e.jsxs(B,{gap:"md",children:[e.jsxs(Q,{cols:2,spacing:"md",children:[e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",tt:"uppercase",fw:500,mb:4,children:"Название"}),e.jsx(r,{fw:500,children:h.name})]}),e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",tt:"uppercase",fw:500,mb:4,children:"Статус"}),e.jsx(f,{color:h.isActive?"green":"gray",variant:"light",children:h.isActive?"Активна":"Неактивна"})]}),e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",tt:"uppercase",fw:500,mb:4,children:"Email владельца"}),e.jsx(r,{fw:500,children:h.ownerEmail||"—"})]}),e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",tt:"uppercase",fw:500,mb:4,children:"ИНН"}),e.jsx(r,{fw:500,children:h.inn||"—"})]}),e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",tt:"uppercase",fw:500,mb:4,children:"Макс. сотрудников"}),e.jsx(r,{fw:500,children:h.maxUsers})]}),e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",tt:"uppercase",fw:500,mb:4,children:"Трафик"}
3),e.jsx(r,{fw:500,children:L(h.trafficLimit)})]}),e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",tt:"uppercase",fw:500,mb:4,children:"Сквад"}),h.squadName?(()=>{const s=U.find(o=>o.name===h.squadName);return e.jsxs(i,{gap:6,wrap:"wrap",children:[e.jsx(r,{fw:500,children:h.squadName}),U.length>0&&(s?e.jsx(Z,{label:`Найден в Remnawave: ${s.membersCount} польз., ${s.inboundsCount} inb.`,children:e.jsx(f,{size:"xs",variant:"light",color:"green",children:"в Remnawave"})}):e.jsx(Z,{label:"Сквад с таким именем не найден в корпоративной Remnawave",children:e.jsx(f,{size:"xs",variant:"light",color:"red",children:"не найден"})}))]})})():e.jsx(r,{fw:500,children:"—"})]}),e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",tt:"uppercase",fw:500,mb:4,children:"Действует до"}),e.jsx(r,{fw:500,children:h.expiresAt?oe(h.expiresAt).format("DD.MM.YYYY"):"—"})]})]}),h.order?.plan&&e.jsxs(O,{p:"md",radius:"md",withBorder:!0,children:[e.jsx(r,{size:"xs",c:"dimmed",tt:"uppercase",fw:500,mb:4,children:"План"}),e.jsx(f,{variant:"outline",size:"lg",children:h.order.plan.name})]}),e.jsx(he,{label:e.jsxs(i,{gap:8,children:[e.jsx(r,{size:"sm",children:"Сотрудники"}),(()=>{const s=h.members.filter(G=>G.user.twoFactorEnabled).length,o=h.members.filter(G=>G.role==="owner"||G.role==="admin"),P=o.filter(G=>G.user.twoFactorEnabled).length;return e.jsx(Z,{label:`2FA включена у ${s} из ${h.members.length} сотрудников (admin/owner: ${P}/${o.length})`,children:e.jsxs(f,{size:"xs",variant:"light",color:P===o.length&&o.length>0?"teal":"yellow",leftSection:e.jsx(Rs,{size:10}),children:["2FA ",s,"/",h.members.length]})})})()]})}),h.members.length>0?e.jsx(a.ScrollContainer,{minWidth:500,children:e.jsxs(a,{verticalSpacing:"sm",highlightOnHover:!0,children:[e.jsx(a.Thead,{children:e.jsxs(a.Tr,{children:[e.jsx(a.Th,{children:"Сотрудник"}),e.jsx(a.Th,{children:"Роль"}),e.jsx(a.Th,{children:"2FA"}),e.jsx(a.Th,{})]})}),e.jsx(a.Tbody,{children:h.members.map(s=>e.jsxs(a.Tr,{children:[e.jsx(a.Td,{children:e.jsxs(i,{gap:"sm",children:[e.jsx(os,{size:"sm",radius:"xl",color:ce[s.role]||"gray",children:s.role==="owner"?e.jsx(Vs,{size:12}):e.jsx(ds,{size:12})}),e.jsxs("div",{children:[e.jsx(r,{size:"sm",fw:500,children:s.user.name||s.user.email.split("@")[0]}),e.jsx(r,{size:"xs",c:"dimmed",children:s.user.email})]})]})}),e.jsx(a.Td,{children:e.jsx(f,{size:"sm",variant:"light",color:ce[s.role]||"gray",children:ve[s.role]||s.role})}),e.jsx(a.Td,{children:s.user.twoFactorEnabled?e.jsx(Z,{label:s.user.twoFactorEnabledAt?`Включена ${oe(s.user.twoFactorEnabledAt).format("DD.MM.YYYY")}`:"Включена",children:e.jsx(f,{size:"sm",variant:"light",color:"teal",leftSection:e.jsx(Rs,{size:12}),children:"включена"})}):e.jsx(f,{size:"sm",variant:"light",color:s.role==="owner"||s.role==="admin"?"yellow":"gray",children:"нет"})}),e.jsx(a.Td,{children:s.user.twoFactorEnabled&&e.jsx(Z,{label:"Сбросить 2FA (для поддержки)",children:e.jsx(le,{variant:"subtle",color:"red",size:"sm",onClick:()=>dr.openConfirmModal({title:"Сбросить 2FA сотруднику?",children:e.jsxs(B,{gap:"sm",children:[e.jsxs(r,{size:"sm",children:["Двухфакторная аутентификация будет отключена для"," ",e.jsx("b",{children:s.user.email}),". Сотрудник сможет войти только по паролю, и при следующем входе ему нужно будет настроить 2FA заново."]}),e.jsx(r,{size:"xs",c:"dimmed",children:"Используйте только когда сотрудник потерял телефон и резервные коды. Действие фиксируется в логах."})]}),labels:{confirm:"Сбросить 2FA",cancel:"Отмена"},confirmProps:{color:"red",leftSection:e.jsx(zs,{size:14})},onConfirm:async()=>{try{const o=await fetch(`/api/admin/corporate/members/${s.id}/reset-2fa`,{method:"POST",headers:{Authorization:`Bearer ${c}`}});if(!o.ok){const P=await o.json();throw new Error(P.message||"Failed")}p.show({title:"2FA сброшена",message:`Для ${s.user.email} 2FA отключена`,color:"orange"}),await w(h.id)}catch(o){p.show({title:"Ошибка",message:o.message,color:"red"})}}}),children:e.jsx(zs,{size:16})})})})]},s.id))})]})}):e.jsx(r,{size:"sm",c:"dimmed",ta:"center",children:"Нет сотрудников"}),e.jsx(he,{label:e.jsxs(i,{gap:6,children:[e.jsx(hs,{size:14}),e.jsx(r,{size:"sm",children:"Telegram-бот"})]})}),e.jsx(Qr,{orgId:h.id}),e.jsx(he,{label:e.jsxs(i,{gap:6,children:[e.jsx(ms,{size:14}),e.jsx(r,{size:"sm",children:"Доп. протоколы (WireGuard / AmneziaWG)"})]})}),e.jsx(Xr,{orgId:h.id}),e.jsxs(i,{justify:"space-between",mt:"md",children:[e.jsx(v,{variant:"light",color:"red",leftSection:e.jsx(Be,{size:16}),onClick:()=>q(h),children:"Удалить"}),e.jsx(v,{variant:"light",onClick:()=>T(!0),leftSection:e.jsx(Ye,{size:16}),children:"Редактировать"})]})]}),h&&z&&e.jsx("form",{onSubmit:E.onSubmit(ee),children:e.jsxs(B,{gap:"md",children:[e.jsx(_,{label:"Название",required:!0,...E.getInputProps("name")}
3),e.jsxs(Q,{cols:2,children:[e.jsx(_,{label:"ИНН",placeholder:"1234567890",...E.getInputProps("inn")}),e.jsx(_,{label:"Email владельца",...E.getInputProps("ownerEmail")})]}),e.jsxs(Q,{cols:2,children:[e.jsx(ze,{label:"Макс. сотрудников",min:1,required:!0,...E.getInputProps("maxUsers")}),e.jsx(_,{label:"Лимит трафика (GB)",placeholder:"Пусто = безлимит",...E.getInputProps("trafficLimit")})]}),e.jsxs(Q,{cols:2,children:[U.length>0?e.jsx(Te,{label:"Сквад в Remnawave",placeholder:"Выберите существующий сквад",searchable:!0,clearable:!0,data:U.map(s=>({value:s.name,label:`${s.name} · ${s.membersCount} польз. · ${s.inboundsCount} inb.`})),value:E.values.squadName||null,onChange:s=>E.setFieldValue("squadName",s||""),description:"Список из корпоративной Remnawave"}):e.jsx(_,{label:"Название сквада",placeholder:"corp_company",description:"Не удалось получить список сквадов из Remnawave — введите имя вручную",...E.getInputProps("squadName")}),e.jsx(Ws,{label:"Действует до",placeholder:"Выберите дату",clearable:!0,value:E.values.expiresAt,onChange:s=>E.setFieldValue("expiresAt",s)})]}),e.jsx(Sr,{label:"Страны (геолокации)",description:"Доступные геолокации корпорации (хранятся в заказе)",placeholder:"Выберите страны",searchable:!0,clearable:!0,data:Object.entries(pr).filter(([s])=>s!=="XX").map(([s,o])=>({value:s,label:`${o} (${s})`})).sort((s,o)=>s.label.localeCompare(o.label,"ru")),value:E.values.requestedServers,onChange:s=>E.setFieldValue("requestedServers",s)}),e.jsx(Xe,{label:"Активна",description:"Выключение деактивирует VPN для всех сотрудников",...E.getInputProps("isActive",{type:"checkbox"})}),e.jsxs(i,{justify:"flex-end",mt:"md",children:[e.jsx(v,{variant:"subtle",onClick:()=>T(!1),children:"Отмена"}),e.jsx(v,{type:"submit",loading:$,leftSection:e.jsx(we,{size:16}),children:"Сохранить"})]})]})})]}),e.jsx(Se,{opened:!!M,onClose:()=>q(null),title:e.jsx(r,{fw:600,c:"red",children:"Удаление организации"}),centered:!0,children:e.jsxs(B,{gap:"md",children:[e.jsxs(r,{children:["Вы уверены, что хотите удалить организацию ",e.jsxs("b",{children:['"',M?.name,'"']}),"?"]}),e.jsx(r,{size:"sm",c:"dimmed",children:"Все сотрудники будут отвязаны от организации. Это действие необратимо."}),e.jsxs(i,{justify:"flex-end",children:[e.jsx(v,{variant:"subtle",onClick:()=>q(null),children:"Отмена"}),e.jsx(v,{color:"red",loading:C,leftSection:e.jsx(Be,{size:16}),onClick:()=>M&&V(M),children:"Удалить"})]})]})})]})}function si(){const{token:c}=Re(),[k,N]=n.useState(!0),[$,F]=n.useState(!1),[g,D]=n.useState(!1),[h,d]=n.useState("unknown"),u=He({initialValues:{remnawaveUrl:"",remnawaveToken:"",isEnabled:!1,defaultSquadPrefix:"corp_"},validate:{remnawaveUrl:(T,M)=>M.isEnabled&&!T?"URL обязателен":T&&!T.startsWith("http")?"URL должен начинаться с http:// или https://":null,remnawaveToken:(T,M)=>M.isEnabled&&!T?"Токен обязателен":null}}),S=async(T,M)=>{try{return(await fetch("/api/settings/corporate-remnawave/test",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`},body:JSON.stringify({url:T,token:M})})).ok?"success":"error"}catch{return"error"}};n.useEffect(()=>{(async()=>{try{const M=await fetch("/api/settings/corporate-remnawave",{headers:{Authorization:`Bearer ${c}`}});if(M.ok){const q=await M.json();if(u.setValues({remnawaveUrl:q.remnawaveUrl||"",remnawaveToken:q.remnawaveToken||"",isEnabled:q.isEnabled||!1,defaultSquadPrefix:q.defaultSquadPrefix||"corp_"}),q.isEnabled&&q.remnawaveUrl&&q.remnawaveToken){D(!0);const C=await S(q.remnawaveUrl,q.remnawaveToken);d(C),D(!1)}}}catch(M){console.error("Failed to load corporate settings:",M)}finally{N(!1)}})()},[c]);const A=async()=>
3{if(!u.values.remnawaveUrl||!u.values.remnawaveToken){p.show({title:"Ошибка",message:"Укажите URL и токен для тестирования",color:"red"});return}D(!0),d("unknown");const T=await S(u.values.remnawaveUrl,u.values.remnawaveToken);d(T),T==="success"?p.show({title:"Успех",message:"Подключение к Remnawave успешно",color:"green"}):p.show({title:"Ошибка подключения",message:"Не удалось подключиться к Remnawave",color:"red"}),D(!1)},z=async T=>{F(!0);try{const M=await fetch("/api/settings/corporate-remnawave",{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`},body:JSON.stringify(T)});if(M.ok)p.show({title:"Сохранено",message:"Настройки корпоративного Remnawave сохранены",color:"green"});else{const q=await M.json();throw new Error(q.message)}}catch(M){p.show({title:"Ошибка",message:M.message||"Не удалось сохранить настройки",color:"red"})}finally{F(!1)}};return k?e.jsx($e,{py:"xl",children:e.jsx(Pe,{})}):e.jsxs(B,{gap:"lg",children:[e.jsx(ie,{color:"blue",variant:"light",icon:e.jsx(Ae,{size:16}),children:"Здесь настраивается отдельная Remnawave панель, которая будет использоваться для корпоративных клиентов. Организации корпоративных клиентов будут создаваться как сквады в этой панели."}),e.jsx("form",{onSubmit:u.onSubmit(z),children:e.jsxs(B,{gap:"md",children:[e.jsxs(je,{withBorder:!0,p:"lg",children:[e.jsxs(i,{justify:"space-between",mb:"md",children:[e.jsxs(i,{children:[e.jsx(ue,{size:"lg",variant:"light",color:"orange",children:e.jsx(xr,{size:20})}),e.jsxs("div",{children:[e.jsx(r,{fw:500,children:"Remnawave для корпоративных клиентов"}),e.jsx(r,{size:"xs",c:"dimmed",children:"Отдельная панель для управления корп. аккаунтами"})]})]}),e.jsx(Xe,{label:"Включено",...u.getInputProps("isEnabled",{type:"checkbox"})})]}),e.jsx(he,{mb:"md"}),e.jsxs(Q,{cols:{base:1,md:2},spacing:"md",children:[e.jsx(_,{label:"URL Remnawave",placeholder:"https://remna.example.com",description:"Адрес панели Remnawave для корп. клиентов",leftSection:e.jsx(Ts,{size:16}),disabled:!u.values.isEnabled,...u.getInputProps("remnawaveUrl")}),e.jsx(_,{label:"API Токен",placeholder:"Токен доступа к API",description:"Токен для авторизации в Remnawave API",type:"password",disabled:!u.values.isEnabled,...u.getInputProps("remnawaveToken")})]}),e.jsx(_,{mt:"md",label:"Префикс сквадов",placeholder:"corp_",description:"Префикс для названий сквадов корп. клиентов",disabled:!u.values.isEnabled,...u.getInputProps("defaultSquadPrefix")}),u.values.isEnabled&&e.jsx(O,{mt:"md",p:"md",bg:"dark.6",radius:"md",children:e.jsxs(i,{justify:"space-between",children:[e.jsxs(i,{children:[e.jsx(r,{size:"sm",children:"Статус подключения:"}),g&&h==="unknown"&&e.jsx(f,{color:"indigo",variant:"light",children:"Проверяем…"}),!g&&h==="unknown"&&e.jsx(f,{color:"gray",variant:"light",children:"Не проверено"}),h==="success"&&e.jsx(f,{color:"green",variant:"light",leftSection:e.jsx(we,{size:12}),children:"Подключено"}),h==="error"&&e.jsx(f,{color:"red",variant:"light",leftSection:e.jsx(Ae,{size:12}),children:"Ошибка"})]}),e.jsx(v,{variant:"light",size:"xs",leftSection:e.jsx(De,{size:14}),loading:g,onClick:A,children:"Проверить подключение"})]})})]}),e.jsx(i,{justify:"flex-end",children:e.jsx(v,{type:"submit",loading:$,children:"Сохранить настройки"})})]})}),e.jsx(ri,{})]})}function ri(){const{token:c}=Re(),[k,N]=n.useState(!0),[$,F]=n.useState(!1),[g,D]=n.useState("ru"),h=He({initialValues:{siteTitle:"EOFVPN Corporate",headerTitle:"EOFVPN Corporate",headerSubtitle:"Корпоративный портал",termsOfService:"",termsOfServiceEn:"",privacyPolicy:"",privacyPolicyEn:"",termsUpdatedAt:"",privacyUpdatedAt:""}});n.useEffect(()=>{(async()=>{try{const u=await fetch("/api/settings/corporate-site",{headers:{Authorization:`Bearer ${c}`}});if(u.ok){const S=await u.json();h.setValues({siteTitle:S.siteTitle||"EOFVPN Corporate",headerTitle:S.headerTitle||S.siteTitle||"EOFVPN Corporate",headerSubtitle:S.headerSubtitle||"Корпоративный портал",termsOfService:S.termsOfService||"",termsOfServiceEn:S.termsOfServiceEn||"",privacyPolicy:S.privacyPolicy||"",privacyPolicyEn:S.privacyPolicyEn||"",termsUpdatedAt:S.termsUpdatedAt||"",privacyUpdatedAt:S.privacyUpdatedAt||""})}}catch(u){console.error("[CorpSite] failed to load:",u)}finally{N(!1)}})()},[c]);const d=async()=>{F(!0);try{const u=await fetch("/api/settings/corporate-site",{method:"PUT",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`},body:JSON.stringify({siteTitle:h.values.siteTitle,headerTitle:h.values.headerTitle,headerSubtitle:h.values.headerSubtitle,termsOfService:h.values.termsOfService,termsOfServiceEn:h.values.termsOfServiceEn,privacyPolicy:h.values.privacyPolicy,privacyPolicyEn:h.values.privacyPolicyEn})});if(!u.ok)throw new Error((await u.json())?.message||"Ошибка сохранения");const S=await u.json();h.setFieldValue("termsUpdatedAt",S.termsUpdatedAt||""),h.setFieldValue("privacyUpdatedAt",S.privacyUpdatedAt||""),p.show({title:"Сохранено",message:"Настройки корпоративного сайта обновлены",color:"green"})}catch(u){p.show({title:"Ошибка",message:u.message||"Не удалось сохранить",color:"red"})}finally{F(!1)}};return k?e.jsx(je,{withBorder:!0,p:"lg",children:e.jsx($e,{py:"md",children:e.jsx(Pe,{})})}):e.jsx(je,{withBorder:!0,p:"lg",children:e.jsxs(B,{gap:"md",children:[e.jsx(i,{justify:"space-between",wrap:"nowrap",children:e.jsxs(i,{children:[e.jsx(ue,{size:"lg",variant:"light",color:"grape",children:e.jsx(Ks,{size:20})}),e.jsxs("div",{children:[e.jsx(r,{fw:500,children:"Брендинг и доÐ
3ºÑƒÐ¼ÐµÐ½Ñ‚Ñ‹ корпоративного сайта"}),e.jsx(r,{size:"xs",c:"dimmed",children:"Заголовок вкладки браузера, текст в шапке и юридические документы (RU / EN)."})]})]})}),e.jsx(he,{}),e.jsx(r,{fw:600,size:"sm",children:"Брендинг"}),e.jsxs(Q,{cols:{base:1,md:2},spacing:"md",children:[e.jsx(_,{label:"Title сайта",description:"Отображается во вкладке браузера",placeholder:"EOFVPN Corporate",leftSection:e.jsx(Ts,{size:16}),...h.getInputProps("siteTitle")}),e.jsx(_,{label:"Заголовок в шапке",description:"Отображается рядом с логотипом",placeholder:"EOFVPN Corporate",...h.getInputProps("headerTitle")}),e.jsx(_,{label:"Подзаголовок в шапке",description:"Маленький текст под заголовком",placeholder:"Корпоративный портал",...h.getInputProps("headerSubtitle")})]}),e.jsx(he,{}),e.jsxs(i,{justify:"space-between",align:"center",children:[e.jsx(r,{fw:600,size:"sm",children:"Юридические документы"}),e.jsx(ys,{size:"xs",value:g,onChange:u=>D(u),data:[{label:"RU",value:"ru"},{label:"EN",value:"en"}]})]}),e.jsx(je,{withBorder:!0,children:e.jsxs(B,{gap:"xs",children:[e.jsxs(i,{justify:"space-between",children:[e.jsxs(r,{fw:600,size:"sm",children:[g==="ru"?"Условия использования":"Terms of Service"," ",e.jsx(f,{size:"xs",variant:"light",color:g==="ru"?"blue":"orange",children:g==="ru"?"RU":"EN"})]}),h.values.termsUpdatedAt&&e.jsxs(r,{size:"xs",c:"dimmed",children:["Обновлено: ",new Date(h.values.termsUpdatedAt).toLocaleDateString("ru-RU")]})]}),g==="ru"?e.jsx(Ce,{placeholder:`# Условия использования
4
5## 1. Общие положения
6...`,minRows:10,maxRows:20,autosize:!0,...h.getInputProps("termsOfService")}):e.jsx(Ce,{placeholder:`# Terms of Service
7
8## 1. General Provisions
9...`,minRows:10,maxRows:20,autosize:!0,...h.getInputProps("termsOfServiceEn")})]})}),e.jsx(je,{withBorder:!0,children:e.jsxs(B,{gap:"xs",children:[e.jsxs(i,{justify:"space-between",children:[e.jsxs(r,{fw:600,size:"sm",children:[g==="ru"?"Политика конфиденциальности":"Privacy Policy"," ",e.jsx(f,{size:"xs",variant:"light",color:g==="ru"?"blue":"orange",children:g==="ru"?"RU":"EN"})]}),h.values.privacyUpdatedAt&&e.jsxs(r,{size:"xs",c:"dimmed",children:["Обновлено: ",new Date(h.values.privacyUpdatedAt).toLocaleDateString("ru-RU")]})]}),g==="ru"?e.jsx(Ce,{placeholder:`# Политика конфиденциальности
10
11## 1. Сбор данных
12...`,minRows:10,maxRows:20,autosize:!0,...h.getInputProps("privacyPolicy")}):e.jsx(Ce,{placeholder:`# Privacy Policy
13
14## 1. Data Collection
15...`,minRows:10,maxRows:20,autosize:!0,...h.getInputProps("privacyPolicyEn")})]})}),e.jsx(i,{justify:"flex-end",children:e.jsx(v,{leftSection:e.jsx(Ss,{size:16}),loading:$,onClick:d,children:"Сохранить"})})]})})}function fs(c){if(!c||c<=0)return"0 B";const k=["B","KB","MB","GB","TB","PB"];let N=c,$=0;for(;N>=1024&&$<k.length-1;)N/=1024,$++;return`${N.toFixed(N>=100?0:N>=10?1:2)} ${k[$]}`}function ii(){const{token:c}=Re(),[k,N]=n.useState([]),[$,F]=n.useState([]),[g,D]=n.useState(!0),[h,d]=n.useState(""),[u]=Cr(h,300),[S,A]=n.useState(null),[z,T]=n.useState(1),[M,q]=n.useState(1),[C,H]=n.useState(0),U=25,[x,E]=n.useState(null),[y,{open:K,close:w}]=Ve(!1),[ee,V]=n.useState(!1),[L,be]=n.useState(null),[ve,ce]=n.useState(!1),Y=He({initialValues:{email:"",name:"",login:"",password:"",role:"member",hwidDeviceLimit:5},validate:{email:m=>m&&!/^\S+@\S+\.\S+$/.test(m)?"Некорректный email":null,login:m=>m&&m.trim().length<2?"Минимум 2 символа":null,password:m=>m&&m.length>0&&m.length<6?"Минимум 6 символов":null}}),re=async()=>{try{const m=await fetch("/api/admin/corporate/organizations",{headers:{Authorization:`Bearer ${c}`}});m.ok&&F(await m.json())}catch(m){console.error("Failed to load orgs:",m)}},s=async()=>{D(!0);try{const m=new URLSearchParams;u.trim()&&m.set("search",u.trim()),S&&m.set("organizationId",S),m.set("page",String(z)),m.set("limit",String(U));const W=await fetch(`/api/admin/corporate/members?${m.toString()}`,{headers:{Authorization:`Bearer ${c}`}});if(W.ok){const te=await W.json();N(te.members||[]),q(te.totalPages||1),H(te.total||0)}}catch(m){console.error("Failed to load members:",m)}finally{D(!1)}};n.useEffect(()=>{re()},[]),n.useEffect(()=>{T(1)},[u,S]),n.useEffect(()=>{s()},[u,S,z]);const o=async m=>{ce(!0),be(null);try{const W=await fetch(`/api/admin/corporate/members/${m}/remnawave`,{headers:{Authorization:`Bearer ${c}`}});if(W.ok){const te=await W.json();be(te),typeof te.hwidDeviceLimit=="number"?Y.setFieldValue("hwidDeviceLimit",te.hwidDeviceLimit):Y.setFieldValue("hwidDeviceLimit",te.planMaxDevices??5)}}catch(W){console.error("Failed to load member details:",W)}finally{ce(!1)}},P=m=>{E(m),Y.setValues({email:m.user.email||"",name:m.user.name||"",login:m.user.login||"",password:"",role:m.role,hwidDeviceLimit:5}),K(),o(m.id)},G=async m=>{if(x){V(!0);try{const W={};m.email!==(x.user.email||"")&&(W.email=m.email),m.name!==(x.user.name||"")&&(W.name=m.name),m.login!==(x.user.login||"")&&(W.login=m.login),m.password&&(W.password=m.password),m.role!==x.role&&(W.role=m.role);const te=L?.hwidDeviceLimit??null;if(m.hwidDeviceLimit!==te&&(W.hwidDeviceLimit=m.hwidDeviceLimit),Object.keys(W).length===0){p.show({title:"Изменений нет",message:"Нечего сохранять",color:"gray"}),V(!1);return}const ge=await fetch(`/api/admin/corporate/members/${x.id}`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`},body:JSON.stringify(W)});if(!ge.ok){const Le=await ge.json().catch(()=>({}));throw new Error(Le.message||"Ошибка сохранения")}p.show({title:"Сохранено",message:"Сотрудник обновлён",color:"green"}),w(),E(null),s()}catch(W){p.show({title:"Ошибка",message:W.message,color:"red"})}finally{V(!1)}}},X=m=>m==="owner"?"yellow":m==="admin"?"blue":"gray",Ne=m=>m==="owner"?"Владелец":m==="admin"?"Админ":"Сотрудник",pe=m=>m==="owner"?e.jsx(Vs,{size:12}):m==="admin"?e.jsx(ds,{size:12}):e.jsx(ds,{size:12});return e.jsxs(B,{children:[e.jsx(je,{withBorder:!0,radius:"md",p:"md",children:e.jsxs(i,{wrap:"wrap",gap:"md",children:[e.jsx(_,{placeholder:"Поиск по email, логину, имени...",leftSection:e.jsx(Tr,{size:14}),rightSection:h?e.jsx(le,{size:"sm",variant:"subtle",color:"gray",onClick:()=>d(""),children:e.jsx(Ps,{size:14})}):null,value:h,onChange:m=>d(m.currentTarget.value),style:{flex:1,minWidth:240}}),e.jsx(Te,{placeholder:"Все компании",clearable:!0,searchable:!0,data:$.map(m=>({value:String(m.id),label:m.name})),value:S,onChange:A,style:{minWidth:220}}),e.jsx(Z,{label:"Обновить",children:e.jsx(le,{variant:"default",onClick:()=>s(),children:e.jsx(De,{size:16})})}),e.jsxs(r,{size:"sm",c:"dimmed",children:["Найдено: ",C]})]})}),g?e.jsx($e,{py:"xl",children:e.jsx(Pe,{})}
15):k.length===0?e.jsx(O,{withBorder:!0,p:"xl",radius:"md",children:e.jsx($e,{children:e.jsxs(B,{align:"center",gap:"xs",children:[e.jsx(ue,{size:"xl",variant:"light",color:"gray",children:e.jsx(ss,{size:28})}),e.jsx(r,{c:"dimmed",children:"Сотрудники не найдены"})]})})}):e.jsxs(je,{withBorder:!0,radius:"md",p:0,children:[e.jsx(a.ScrollContainer,{minWidth:900,children:e.jsxs(a,{verticalSpacing:"sm",highlightOnHover:!0,children:[e.jsx(a.Thead,{children:e.jsxs(a.Tr,{children:[e.jsx(a.Th,{children:"Сотрудник"}),e.jsx(a.Th,{children:"Email"}),e.jsx(a.Th,{children:"Логин"}),e.jsx(a.Th,{children:"Компания"}),e.jsx(a.Th,{children:"Роль"}),e.jsx(a.Th,{children:"Статус"}),e.jsx(a.Th,{style:{width:80}})]})}),e.jsx(a.Tbody,{children:k.map(m=>{const W=!!m.user.blockedAt;return e.jsxs(a.Tr,{children:[e.jsx(a.Td,{children:e.jsxs(i,{gap:"sm",wrap:"nowrap",children:[e.jsx(os,{size:"sm",radius:"xl",src:m.user.avatar||void 0,children:(m.user.name||m.user.email||"?").charAt(0).toUpperCase()}),e.jsxs(Ee,{children:[e.jsx(r,{size:"sm",fw:500,children:m.user.name||"—"}),m.remnawaveUsername&&e.jsxs(r,{size:"xs",c:"dimmed",children:["RW: ",m.remnawaveUsername]})]})]})}),e.jsx(a.Td,{children:e.jsx(r,{size:"sm",style:{wordBreak:"break-all"},children:m.user.email||"—"})}),e.jsx(a.Td,{children:e.jsx(r,{size:"sm",children:m.user.login||"—"})}),e.jsx(a.Td,{children:e.jsxs(B,{gap:2,children:[e.jsx(Es,{size:"sm",fw:500,onClick:te=>{te.preventDefault(),A(m.organization.id)},style:{cursor:"pointer"},children:m.organization.name}),m.organization.squadName&&e.jsxs(r,{size:"xs",c:"dimmed",children:["squad: ",m.organization.squadName]})]})}),e.jsx(a.Td,{children:e.jsx(f,{color:X(m.role),leftSection:pe(m.role),variant:"light",children:Ne(m.role)})}),e.jsx(a.Td,{children:W?e.jsx(f,{color:"red",variant:"light",children:"Заблокирован"}):m.organization.isActive?e.jsx(f,{color:"green",variant:"light",children:"Активен"}):e.jsx(f,{color:"orange",variant:"light",children:"Корп. неактивна"})}),e.jsx(a.Td,{children:e.jsx(Z,{label:"Редактировать",children:e.jsx(le,{variant:"subtle",onClick:()=>P(m),children:e.jsx(Ye,{size:16})})})})]},m.id)})})]})}),M>1&&e.jsx(i,{justify:"center",p:"md",children:e.jsx(xs,{total:M,value:z,onChange:T})})]}),e.jsx(Se,{opened:y,onClose:()=>{w(),E(null),be(null)},title:e.jsxs(i,{gap:"xs",children:[e.jsx(Ye,{size:18}),e.jsx(r,{fw:600,children:"Редактирование сотрудника"})]}),size:"md",centered:!0,children:x&&e.jsx("form",{onSubmit:Y.onSubmit(G),children:e.jsxs(B,{children:[e.jsx(ie,{color:"blue",variant:"light",icon:e.jsx(Ie,{size:16}),children:e.jsxs(r,{size:"sm",children:["Компания: ",e.jsx("b",{children:x.organization.name})]})}),ve?e.jsx(O,{withBorder:!0,radius:"md",p:"md",children:e.jsx($e,{children:e.jsx(Pe,{size:"sm"})})}):L&&L.found?(()=>{const m=L.usedTrafficBytes,W=L.trafficLimitBytes,te=!W||W<=0,ge=te?0:Math.min(100,Math.round(m/W*100)),Le=ge>=90?"red":ge>=70?"orange":"teal",Oe=L.devicesCount,fe=L.hwidDeviceLimit,Fe=fe?Math.min(100,Math.round(Oe/fe*100)):0,t=fe&&Oe>=fe?"red":fe&&Oe>=fe*.8?"orange":"blue",j=L.status==="ACTIVE"?"green":L.status==="DISABLED"?"red":L.status==="EXPIRED"?"orange":L.status==="LIMITED"?"yellow":"gray";return e.jsxs(O,{withBorder:!0,radius:"md",p:"md",children:[e.jsxs(i,{justify:"space-between",mb:"sm",wrap:"wrap",children:[e.jsxs(i,{gap:6,children:[e.jsx(ue,{size:"sm",variant:"light",color:"teal",children:e.jsx(hr,{size:12})}),e.jsx(r,{size:"xs",c:"dimmed",tt:"uppercase",fw:600,children:"Активность в Remnawave"})]}),L.status&&e.jsx(f,{size:"sm",color:j,variant:"light",children:L.status})]}),e.jsxs(Q,{cols:2,spacing:"md",children:[e.jsxs(i,{gap:"md",wrap:"nowrap",children:[e.jsx(Us,{size:84,thickness:9,sections:[{value:te?100:ge,color:Le}],label:e.jsx($e,{children:e.jsx(r,{size:"xs",fw:700,children:te?"∞":`${ge}%`})})}),e.jsxs(Ee,{style:{flex:1,minWidth:0},children:[e.jsx(r,{size:"xs",c:"dimmed",tt:"uppercase",fw:600,children:"Трафик"}),e.jsx(r,{size:"sm",fw:600,mt:2,style:{lineHeight:1.2},children:fs(m)}),e.jsxs(r,{size:"xs",c:"dimmed",mt:2,children:["из ",te?"∞":fs(W)]}),L.lifetimeUsedTrafficBytes>0&&e.jsxs(r,{size:"xs",c:"dimmed",mt:4,children:["всего: ",fs(L.lifetimeUsedTrafficBytes)]})]})]}),e.jsxs(i,{gap:"md",wrap:"nowrap",children:[e.jsx(Us,{size:84,thickness:9,sections:[{value:fe?Fe:Oe>0?100:0,color:t}],label:e.jsx($e,{children:e.jsx(ue,{size:"sm",variant:"transparent",color:t,children:e.jsx(Ms,{size:16})})})}),e.jsxs(Ee,{style:{flex:1,minWidth:0},children:[e.jsx(r,{size:"xs",c:"dimmed",tt:"uppercase",fw:600,children:"Устройства"}),e.jsxs(r,{size:"sm",fw:600,mt:2,style:{lineHeight:1.2},children:[Oe,fe?` / ${fe}`:""]}),e.jsx(r,{size:"xs",c:"dimmed",mt:2,children:fe?"активных подключений":"без лимита"}),L.onlineAt&&e.jsxs(r,{size:"xs",c:"dimmed",mt:4,children:["онлайн: ",oe(L.onlineAt).format("DD.MM HH:mm")]})]})]})]}),L.expireAt&&e.jsxs(e.Fragment,{children:[e.jsx(he,{my:"sm"}),e.jsxs(i,{justify:"space-between",children:[e.jsxs(i,{gap:6,children:[e.jsx(mr,{size:14}),e.jsx(r,{size:"xs",c:"dimmed",children:"Истекает"})]}),e.jsx(r,{size:"xs",fw:500,children:oe(L.expireAt).format("DD.MM.YYYY HH:mm")}
15)]})]})]})})():L&&!L.found?e.jsx(ie,{color:"orange",variant:"light",icon:e.jsx(Ae,{size:16}),children:e.jsx(r,{size:"sm",children:"Аккаунт ещё не создан в корпоративном Remnawave"})}):null,x.corpSubscriptionUrl?e.jsxs(O,{withBorder:!0,radius:"md",p:"sm",children:[e.jsxs(i,{gap:6,mb:6,children:[e.jsx(ue,{size:"sm",variant:"light",color:"grape",children:e.jsx(Zs,{size:12})}),e.jsx(r,{size:"xs",c:"dimmed",tt:"uppercase",fw:600,children:"Ссылка на подписку"})]}),e.jsx(_,{readOnly:!0,value:x.corpSubscriptionUrl,onClick:m=>m.currentTarget.select(),rightSectionWidth:70,rightSection:e.jsxs(i,{gap:4,wrap:"nowrap",pr:4,children:[e.jsx(Je,{value:x.corpSubscriptionUrl,timeout:1500,children:({copied:m,copy:W})=>e.jsx(Z,{label:m?"Скопировано":"Копировать",children:e.jsx(le,{size:"sm",variant:"subtle",color:m?"green":"gray",onClick:W,children:m?e.jsx(we,{size:14}):e.jsx(Ke,{size:14})})})}),e.jsx(Z,{label:"Открыть в новой вкладке",children:e.jsx(le,{size:"sm",variant:"subtle",color:"gray",component:"a",href:x.corpSubscriptionUrl,target:"_blank",rel:"noopener noreferrer",children:e.jsx(Js,{size:14})})})]}),styles:{input:{fontFamily:"monospace",fontSize:12}}})]}):e.jsx(ie,{color:"yellow",variant:"light",icon:e.jsx(Ae,{size:16}),children:e.jsx(r,{size:"sm",children:"Подписка ещё настраивается в Remnawave"})}),e.jsx(_,{label:"Email",placeholder:"[email protected]",...Y.getInputProps("email")}),e.jsx(_,{label:"Имя",placeholder:"Иван Иванов",...Y.getInputProps("name")}),e.jsx(_,{label:"Логин",placeholder:"username",...Y.getInputProps("login")}),e.jsx(As,{label:"Новый пароль",placeholder:"Оставьте пустым, чтобы не менять",description:"Минимум 6 символов",...Y.getInputProps("password")}),e.jsx(ze,{label:"Лимит устройств",description:L?`Максимум по плану: ${L.planMaxDevices}`:"Загрузка лимита плана…",min:1,max:L?.planMaxDevices??100,leftSection:e.jsx(Ms,{size:14}),...Y.getInputProps("hwidDeviceLimit")}),e.jsx(Te,{label:"Роль",data:[{value:"owner",label:"Владелец"},{value:"admin",label:"Администратор"},{value:"member",label:"Сотрудник"}],value:Y.values.role,onChange:m=>Y.setFieldValue("role",m||"member")}),e.jsxs(i,{justify:"flex-end",mt:"md",children:[e.jsx(v,{variant:"subtle",onClick:()=>{w(),E(null),be(null)},children:"Отмена"}),e.jsx(v,{type:"submit",loading:ee,leftSection:e.jsx(we,{size:16}),children:"Сохранить"})]})]})})})]})}function Vi(){const[c,k]=nr();lr();const N=c.get("tab")||"corporations",$=F=>{F&&k({tab:F})};return e.jsxs(ks,{size:"xl",py:"md",children:[e.jsxs(i,{mb:"lg",children:[e.jsx(ue,{size:"xl",variant:"gradient",gradient:{from:"orange",to:"red"},children:e.jsx(Ie,{size:28})}),e.jsxs("div",{children:[e.jsx(ke,{order:2,children:"Корпорации"}),e.jsx(r,{c:"dimmed",size:"sm",children:"Управление корпоративными клиентами"})]})]}),e.jsxs(ne,{value:N,onChange:$,children:[e.jsxs(ne.List,{mb:"lg",children:[e.jsx(ne.Tab,{value:"corporations",leftSection:e.jsx(Ie,{size:16}),children:"Корпорации"}),e.jsx(ne.Tab,{value:"members",leftSection:e.jsx(ss,{size:16}),children:"Сотрудники"}),e.jsx(ne.Tab,{value:"orders",leftSection:e.jsx(Xs,{size:16}),children:"Заказы"}),e.jsx(ne.Tab,{value:"plans",leftSection:e.jsx(Ie,{size:16}),children:"Планы"}),e.jsx(ne.Tab,{value:"access",leftSection:e.jsx(ms,{size:16}),children:"Доступ"}),e.jsx(ne.Tab,{value:"nodes",leftSection:e.jsx(Is,{size:16}),children:"Ноды"}),e.jsx(ne.Tab,{value:"access-log",leftSection:e.jsx($s,{size:16}),children:"Журнал"}),e.jsx(ne.Tab,{value:"invoices",leftSection:e.jsx(Ks,{size:16}),children:"Счета"}),e.jsx(ne.Tab,{value:"settings",leftSection:e.jsx(or,{size:16}),children:"Настройки Remnawave"})]}),e.jsx(ne.Panel,{value:"corporations",children:e.jsx(ei,{})}),e.jsx(ne.Panel,{value:"members",children:e.jsx(ii,{})}),e.jsx(ne.Panel,{value:"orders",children:e.jsx(Dr,{embedded:!0})}),e.jsx(ne.Panel,{value:"plans",children:e.jsx(Rr,{embedded:!0})}),e.jsx(ne.Panel,{value:"access",children:e.jsx(Lr,{})}),e.jsx(ne.Panel,{value:"nodes",children:e.jsx(Fr,{})}),e.jsx(ne.Panel,{value:"access-log",children:e.jsx(qr,{})}),e.jsx(ne.Panel,{value:"invoices",children:e.jsx(Yr,{})}),e.jsx(ne.Panel,{value:"settings",children:e.jsx(si,{})})]})]})}export{Vi 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.