diff --git a/dist/assets/index-CELGNVNm.js b/dist/assets/index-CELGNVNm.js new file mode 100644 index 0000000..430ec4b --- /dev/null +++ b/dist/assets/index-CELGNVNm.js @@ -0,0 +1,161 @@ +var mm=a=>{throw TypeError(a)};var P0=(a,i,c)=>i.has(a)||mm("Cannot "+c);var C=(a,i,c)=>(P0(a,i,"read from private field"),c?c.call(a):i.get(a)),ie=(a,i,c)=>i.has(a)?mm("Cannot add the same private member more than once"):i instanceof WeakSet?i.add(a):i.set(a,c),W=(a,i,c,r)=>(P0(a,i,"write to private field"),r?r.call(a,c):i.set(a,c),c),Se=(a,i,c)=>(P0(a,i,"access private method"),c);var co=(a,i,c,r)=>({set _(d){W(a,i,d,c)},get _(){return C(a,i,r)}});(function(){const i=document.createElement("link").relList;if(i&&i.supports&&i.supports("modulepreload"))return;for(const d of document.querySelectorAll('link[rel="modulepreload"]'))r(d);new MutationObserver(d=>{for(const f of d)if(f.type==="childList")for(const g of f.addedNodes)g.tagName==="LINK"&&g.rel==="modulepreload"&&r(g)}).observe(document,{childList:!0,subtree:!0});function c(d){const f={};return d.integrity&&(f.integrity=d.integrity),d.referrerPolicy&&(f.referrerPolicy=d.referrerPolicy),d.crossOrigin==="use-credentials"?f.credentials="include":d.crossOrigin==="anonymous"?f.credentials="omit":f.credentials="same-origin",f}function r(d){if(d.ep)return;d.ep=!0;const f=c(d);fetch(d.href,f)}})();function Gp(a){return a&&a.__esModule&&Object.prototype.hasOwnProperty.call(a,"default")?a.default:a}var W0={exports:{}},yc={};/** + * @license React + * react-jsx-runtime.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var pm;function zv(){if(pm)return yc;pm=1;var a=Symbol.for("react.transitional.element"),i=Symbol.for("react.fragment");function c(r,d,f){var g=null;if(f!==void 0&&(g=""+f),d.key!==void 0&&(g=""+d.key),"key"in d){f={};for(var v in d)v!=="key"&&(f[v]=d[v])}else f=d;return d=f.ref,{$$typeof:a,type:r,key:g,ref:d!==void 0?d:null,props:f}}return yc.Fragment=i,yc.jsx=c,yc.jsxs=c,yc}var gm;function Dv(){return gm||(gm=1,W0.exports=zv()),W0.exports}var l=Dv(),J0={exports:{}},ve={};/** + * @license React + * react.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var _m;function Lv(){if(_m)return ve;_m=1;var a=Symbol.for("react.transitional.element"),i=Symbol.for("react.portal"),c=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),d=Symbol.for("react.profiler"),f=Symbol.for("react.consumer"),g=Symbol.for("react.context"),v=Symbol.for("react.forward_ref"),h=Symbol.for("react.suspense"),m=Symbol.for("react.memo"),_=Symbol.for("react.lazy"),y=Symbol.for("react.activity"),b=Symbol.iterator;function N(R){return R===null||typeof R!="object"?null:(R=b&&R[b]||R["@@iterator"],typeof R=="function"?R:null)}var S={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},E=Object.assign,T={};function O(R,V,K){this.props=R,this.context=V,this.refs=T,this.updater=K||S}O.prototype.isReactComponent={},O.prototype.setState=function(R,V){if(typeof R!="object"&&typeof R!="function"&&R!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,R,V,"setState")},O.prototype.forceUpdate=function(R){this.updater.enqueueForceUpdate(this,R,"forceUpdate")};function H(){}H.prototype=O.prototype;function z(R,V,K){this.props=R,this.context=V,this.refs=T,this.updater=K||S}var G=z.prototype=new H;G.constructor=z,E(G,O.prototype),G.isPureReactComponent=!0;var Y=Array.isArray;function J(){}var $={H:null,A:null,T:null,S:null},X=Object.prototype.hasOwnProperty;function ae(R,V,K){var te=K.ref;return{$$typeof:a,type:R,key:V,ref:te!==void 0?te:null,props:K}}function me(R,V){return ae(R.type,V,R.props)}function he(R){return typeof R=="object"&&R!==null&&R.$$typeof===a}function Ce(R){var V={"=":"=0",":":"=2"};return"$"+R.replace(/[=:]/g,function(K){return V[K]})}var re=/\/+/g;function _e(R,V){return typeof R=="object"&&R!==null&&R.key!=null?Ce(""+R.key):V.toString(36)}function de(R){switch(R.status){case"fulfilled":return R.value;case"rejected":throw R.reason;default:switch(typeof R.status=="string"?R.then(J,J):(R.status="pending",R.then(function(V){R.status==="pending"&&(R.status="fulfilled",R.value=V)},function(V){R.status==="pending"&&(R.status="rejected",R.reason=V)})),R.status){case"fulfilled":return R.value;case"rejected":throw R.reason}}throw R}function U(R,V,K,te,pe){var be=typeof R;(be==="undefined"||be==="boolean")&&(R=null);var De=!1;if(R===null)De=!0;else switch(be){case"bigint":case"string":case"number":De=!0;break;case"object":switch(R.$$typeof){case a:case i:De=!0;break;case _:return De=R._init,U(De(R._payload),V,K,te,pe)}}if(De)return pe=pe(R),De=te===""?"."+_e(R,0):te,Y(pe)?(K="",De!=null&&(K=De.replace(re,"$&/")+"/"),U(pe,V,K,"",function(Wn){return Wn})):pe!=null&&(he(pe)&&(pe=me(pe,K+(pe.key==null||R&&R.key===pe.key?"":(""+pe.key).replace(re,"$&/")+"/")+De)),V.push(pe)),1;De=0;var jt=te===""?".":te+":";if(Y(R))for(var Je=0;Je>>1,Te=U[Ee];if(0>>1;Eed(K,se))ted(pe,K)?(U[Ee]=pe,U[te]=se,Ee=te):(U[Ee]=K,U[V]=se,Ee=V);else if(ted(pe,se))U[Ee]=pe,U[te]=se,Ee=te;else break e}}return I}function d(U,I){var se=U.sortIndex-I.sortIndex;return se!==0?se:U.id-I.id}if(a.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var f=performance;a.unstable_now=function(){return f.now()}}else{var g=Date,v=g.now();a.unstable_now=function(){return g.now()-v}}var h=[],m=[],_=1,y=null,b=3,N=!1,S=!1,E=!1,T=!1,O=typeof setTimeout=="function"?setTimeout:null,H=typeof clearTimeout=="function"?clearTimeout:null,z=typeof setImmediate<"u"?setImmediate:null;function G(U){for(var I=c(m);I!==null;){if(I.callback===null)r(m);else if(I.startTime<=U)r(m),I.sortIndex=I.expirationTime,i(h,I);else break;I=c(m)}}function Y(U){if(E=!1,G(U),!S)if(c(h)!==null)S=!0,J||(J=!0,Ce());else{var I=c(m);I!==null&&de(Y,I.startTime-U)}}var J=!1,$=-1,X=5,ae=-1;function me(){return T?!0:!(a.unstable_now()-aeU&&me());){var Ee=y.callback;if(typeof Ee=="function"){y.callback=null,b=y.priorityLevel;var Te=Ee(y.expirationTime<=U);if(U=a.unstable_now(),typeof Te=="function"){y.callback=Te,G(U),I=!0;break t}y===c(h)&&r(h),G(U)}else r(h);y=c(h)}if(y!==null)I=!0;else{var R=c(m);R!==null&&de(Y,R.startTime-U),I=!1}}break e}finally{y=null,b=se,N=!1}I=void 0}}finally{I?Ce():J=!1}}}var Ce;if(typeof z=="function")Ce=function(){z(he)};else if(typeof MessageChannel<"u"){var re=new MessageChannel,_e=re.port2;re.port1.onmessage=he,Ce=function(){_e.postMessage(null)}}else Ce=function(){O(he,0)};function de(U,I){$=O(function(){U(a.unstable_now())},I)}a.unstable_IdlePriority=5,a.unstable_ImmediatePriority=1,a.unstable_LowPriority=4,a.unstable_NormalPriority=3,a.unstable_Profiling=null,a.unstable_UserBlockingPriority=2,a.unstable_cancelCallback=function(U){U.callback=null},a.unstable_forceFrameRate=function(U){0>U||125Ee?(U.sortIndex=se,i(m,U),c(h)===null&&U===c(m)&&(E?(H($),$=-1):E=!0,de(Y,se-Ee))):(U.sortIndex=Te,i(h,U),S||N||(S=!0,J||(J=!0,Ce()))),U},a.unstable_shouldYield=me,a.unstable_wrapCallback=function(U){var I=b;return function(){var se=b;b=I;try{return U.apply(this,arguments)}finally{b=se}}}})(nd)),nd}var xm;function Bv(){return xm||(xm=1,td.exports=kv()),td.exports}var ld={exports:{}},Bt={};/** + * @license React + * react-dom.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var bm;function Uv(){if(bm)return Bt;bm=1;var a=Kd();function i(h){var m="https://react.dev/errors/"+h;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(a)}catch(i){console.error(i)}}return a(),ld.exports=Uv(),ld.exports}/** + * @license React + * react-dom-client.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Sm;function $v(){if(Sm)return xc;Sm=1;var a=Bv(),i=Kd(),c=Hv();function r(e){var t="https://react.dev/errors/"+e;if(1Te||(e.current=Ee[Te],Ee[Te]=null,Te--)}function K(e,t){Te++,Ee[Te]=e.current,e.current=t}var te=R(null),pe=R(null),be=R(null),De=R(null);function jt(e,t){switch(K(be,t),K(pe,e),K(te,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?B1(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=B1(t),e=U1(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}V(te),K(te,e)}function Je(){V(te),V(pe),V(be)}function Wn(e){e.memoizedState!==null&&K(De,e);var t=te.current,n=U1(t,e.type);t!==n&&(K(pe,e),K(te,n))}function fl(e){pe.current===e&&(V(te),V(pe)),De.current===e&&(V(De),pc._currentValue=se)}var $l,ql;function we(e){if($l===void 0)try{throw Error()}catch(n){var t=n.stack.trim().match(/\n( *(at )?)/);$l=t&&t[1]||"",ql=-1)":-1o||w[s]!==L[o]){var q=` +`+w[s].replace(" at new "," at ");return e.displayName&&q.includes("")&&(q=q.replace("",e.displayName)),q}while(1<=s&&0<=o);break}}}finally{qt=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:"")?we(n):""}function Ke(e,t){switch(e.tag){case 26:case 27:case 5:return we(e.type);case 16:return we("Lazy");case 13:return e.child!==t&&t!==null?we("Suspense Fallback"):we("Suspense");case 19:return we("SuspenseList");case 0:case 15:return hl(e.type,!1);case 11:return hl(e.type.render,!1);case 1:return hl(e.type,!0);case 31:return we("Activity");default:return""}}function Pt(e){try{var t="",n=null;do t+=Ke(e,n),n=e,e=e.return;while(e);return t}catch(s){return` +Error generating stack: `+s.message+` +`+s.stack}}var ms=Object.prototype.hasOwnProperty,ps=a.unstable_scheduleCallback,Uo=a.unstable_cancelCallback,dg=a.unstable_shouldYield,fg=a.unstable_requestPaint,fn=a.unstable_now,hg=a.unstable_getCurrentPriorityLevel,m2=a.unstable_ImmediatePriority,p2=a.unstable_UserBlockingPriority,Vc=a.unstable_NormalPriority,mg=a.unstable_LowPriority,g2=a.unstable_IdlePriority,pg=a.log,gg=a.unstable_setDisableYieldValue,Ei=null,hn=null;function Gl(e){if(typeof pg=="function"&&gg(e),hn&&typeof hn.setStrictMode=="function")try{hn.setStrictMode(Ei,e)}catch{}}var mn=Math.clz32?Math.clz32:yg,_g=Math.log,vg=Math.LN2;function yg(e){return e>>>=0,e===0?32:31-(_g(e)/vg|0)|0}var Qc=256,Yc=262144,Ic=4194304;function Ta(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function Xc(e,t,n){var s=e.pendingLanes;if(s===0)return 0;var o=0,u=e.suspendedLanes,p=e.pingedLanes;e=e.warmLanes;var x=s&134217727;return x!==0?(s=x&~u,s!==0?o=Ta(s):(p&=x,p!==0?o=Ta(p):n||(n=x&~e,n!==0&&(o=Ta(n))))):(x=s&~u,x!==0?o=Ta(x):p!==0?o=Ta(p):n||(n=s&~e,n!==0&&(o=Ta(n)))),o===0?0:t!==0&&t!==o&&(t&u)===0&&(u=o&-o,n=t&-t,u>=n||u===32&&(n&4194048)!==0)?t:o}function Ti(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function xg(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function _2(){var e=Ic;return Ic<<=1,(Ic&62914560)===0&&(Ic=4194304),e}function Ho(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function Ri(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function bg(e,t,n,s,o,u){var p=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var x=e.entanglements,w=e.expirationTimes,L=e.hiddenUpdates;for(n=p&~n;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var Eg=/[\n"\\]/g;function Mn(e){return e.replace(Eg,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function Qo(e,t,n,s,o,u,p,x){e.name="",p!=null&&typeof p!="function"&&typeof p!="symbol"&&typeof p!="boolean"?e.type=p:e.removeAttribute("type"),t!=null?p==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+An(t)):e.value!==""+An(t)&&(e.value=""+An(t)):p!=="submit"&&p!=="reset"||e.removeAttribute("value"),t!=null?Yo(e,p,An(t)):n!=null?Yo(e,p,An(n)):s!=null&&e.removeAttribute("value"),o==null&&u!=null&&(e.defaultChecked=!!u),o!=null&&(e.checked=o&&typeof o!="function"&&typeof o!="symbol"),x!=null&&typeof x!="function"&&typeof x!="symbol"&&typeof x!="boolean"?e.name=""+An(x):e.removeAttribute("name")}function A2(e,t,n,s,o,u,p,x){if(u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(e.type=u),t!=null||n!=null){if(!(u!=="submit"&&u!=="reset"||t!=null)){Vo(e);return}n=n!=null?""+An(n):"",t=t!=null?""+An(t):n,x||t===e.value||(e.value=t),e.defaultValue=t}s=s??o,s=typeof s!="function"&&typeof s!="symbol"&&!!s,e.checked=x?e.checked:!!s,e.defaultChecked=!!s,p!=null&&typeof p!="function"&&typeof p!="symbol"&&typeof p!="boolean"&&(e.name=p),Vo(e)}function Yo(e,t,n){t==="number"&&Pc(e.ownerDocument)===e||e.defaultValue===""+n||(e.defaultValue=""+n)}function bs(e,t,n,s){if(e=e.options,t){t={};for(var o=0;o"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Po=!1;if(gl)try{var zi={};Object.defineProperty(zi,"passive",{get:function(){Po=!0}}),window.addEventListener("test",zi,zi),window.removeEventListener("test",zi,zi)}catch{Po=!1}var Vl=null,Wo=null,Jc=null;function B2(){if(Jc)return Jc;var e,t=Wo,n=t.length,s,o="value"in Vl?Vl.value:Vl.textContent,u=o.length;for(e=0;e=ki),F2=" ",V2=!1;function Q2(e,t){switch(e){case"keyup":return t_.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Y2(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var ws=!1;function l_(e,t){switch(e){case"compositionend":return Y2(t);case"keypress":return t.which!==32?null:(V2=!0,F2);case"textInput":return e=t.data,e===F2&&V2?null:e;default:return null}}function a_(e,t){if(ws)return e==="compositionend"||!lu&&Q2(e,t)?(e=B2(),Jc=Wo=Vl=null,ws=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=s}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=ef(n)}}function nf(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?nf(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function lf(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Pc(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href=="string"}catch{n=!1}if(n)e=t.contentWindow;else break;t=Pc(e.document)}return t}function iu(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var f_=gl&&"documentMode"in document&&11>=document.documentMode,Cs=null,cu=null,$i=null,ru=!1;function af(e,t,n){var s=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;ru||Cs==null||Cs!==Pc(s)||(s=Cs,"selectionStart"in s&&iu(s)?s={start:s.selectionStart,end:s.selectionEnd}:(s=(s.ownerDocument&&s.ownerDocument.defaultView||window).getSelection(),s={anchorNode:s.anchorNode,anchorOffset:s.anchorOffset,focusNode:s.focusNode,focusOffset:s.focusOffset}),$i&&Hi($i,s)||($i=s,s=Yr(cu,"onSelect"),0>=p,o-=p,Jn=1<<32-mn(t)+o|n<je?(ze=le,le=null):ze=le.sibling;var He=k(M,le,D[je],F);if(He===null){le===null&&(le=ze);break}e&&le&&He.alternate===null&&t(M,le),A=u(He,A,je),Ue===null?ce=He:Ue.sibling=He,Ue=He,le=ze}if(je===D.length)return n(M,le),Le&&vl(M,je),ce;if(le===null){for(;jeje?(ze=le,le=null):ze=le.sibling;var fa=k(M,le,He.value,F);if(fa===null){le===null&&(le=ze);break}e&&le&&fa.alternate===null&&t(M,le),A=u(fa,A,je),Ue===null?ce=fa:Ue.sibling=fa,Ue=fa,le=ze}if(He.done)return n(M,le),Le&&vl(M,je),ce;if(le===null){for(;!He.done;je++,He=D.next())He=Q(M,He.value,F),He!==null&&(A=u(He,A,je),Ue===null?ce=He:Ue.sibling=He,Ue=He);return Le&&vl(M,je),ce}for(le=s(le);!He.done;je++,He=D.next())He=B(le,M,je,He.value,F),He!==null&&(e&&He.alternate!==null&&le.delete(He.key===null?je:He.key),A=u(He,A,je),Ue===null?ce=He:Ue.sibling=He,Ue=He);return e&&le.forEach(function(Ov){return t(M,Ov)}),Le&&vl(M,je),ce}function Ie(M,A,D,F){if(typeof D=="object"&&D!==null&&D.type===E&&D.key===null&&(D=D.props.children),typeof D=="object"&&D!==null){switch(D.$$typeof){case N:e:{for(var ce=D.key;A!==null;){if(A.key===ce){if(ce=D.type,ce===E){if(A.tag===7){n(M,A.sibling),F=o(A,D.props.children),F.return=M,M=F;break e}}else if(A.elementType===ce||typeof ce=="object"&&ce!==null&&ce.$$typeof===X&&Ha(ce)===A.type){n(M,A.sibling),F=o(A,D.props),Yi(F,D),F.return=M,M=F;break e}n(M,A);break}else t(M,A);A=A.sibling}D.type===E?(F=Da(D.props.children,M.mode,F,D.key),F.return=M,M=F):(F=or(D.type,D.key,D.props,null,M.mode,F),Yi(F,D),F.return=M,M=F)}return p(M);case S:e:{for(ce=D.key;A!==null;){if(A.key===ce)if(A.tag===4&&A.stateNode.containerInfo===D.containerInfo&&A.stateNode.implementation===D.implementation){n(M,A.sibling),F=o(A,D.children||[]),F.return=M,M=F;break e}else{n(M,A);break}else t(M,A);A=A.sibling}F=pu(D,M.mode,F),F.return=M,M=F}return p(M);case X:return D=Ha(D),Ie(M,A,D,F)}if(de(D))return ne(M,A,D,F);if(Ce(D)){if(ce=Ce(D),typeof ce!="function")throw Error(r(150));return D=ce.call(D),fe(M,A,D,F)}if(typeof D.then=="function")return Ie(M,A,gr(D),F);if(D.$$typeof===z)return Ie(M,A,fr(M,D),F);_r(M,D)}return typeof D=="string"&&D!==""||typeof D=="number"||typeof D=="bigint"?(D=""+D,A!==null&&A.tag===6?(n(M,A.sibling),F=o(A,D),F.return=M,M=F):(n(M,A),F=mu(D,M.mode,F),F.return=M,M=F),p(M)):n(M,A)}return function(M,A,D,F){try{Qi=0;var ce=Ie(M,A,D,F);return Bs=null,ce}catch(le){if(le===ks||le===mr)throw le;var Ue=gn(29,le,null,M.mode);return Ue.lanes=F,Ue.return=M,Ue}finally{}}}var qa=Tf(!0),Rf=Tf(!1),Zl=!1;function Eu(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Tu(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Kl(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Pl(e,t,n){var s=e.updateQueue;if(s===null)return null;if(s=s.shared,($e&2)!==0){var o=s.pending;return o===null?t.next=t:(t.next=o.next,o.next=t),s.pending=t,t=rr(e),ff(e,null,n),t}return cr(e,s,t,n),rr(e)}function Ii(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,(n&4194048)!==0)){var s=t.lanes;s&=e.pendingLanes,n|=s,t.lanes=n,y2(e,n)}}function Ru(e,t){var n=e.updateQueue,s=e.alternate;if(s!==null&&(s=s.updateQueue,n===s)){var o=null,u=null;if(n=n.firstBaseUpdate,n!==null){do{var p={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};u===null?o=u=p:u=u.next=p,n=n.next}while(n!==null);u===null?o=u=t:u=u.next=t}else o=u=t;n={baseState:s.baseState,firstBaseUpdate:o,lastBaseUpdate:u,shared:s.shared,callbacks:s.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var Au=!1;function Xi(){if(Au){var e=Ls;if(e!==null)throw e}}function Zi(e,t,n,s){Au=!1;var o=e.updateQueue;Zl=!1;var u=o.firstBaseUpdate,p=o.lastBaseUpdate,x=o.shared.pending;if(x!==null){o.shared.pending=null;var w=x,L=w.next;w.next=null,p===null?u=L:p.next=L,p=w;var q=e.alternate;q!==null&&(q=q.updateQueue,x=q.lastBaseUpdate,x!==p&&(x===null?q.firstBaseUpdate=L:x.next=L,q.lastBaseUpdate=w))}if(u!==null){var Q=o.baseState;p=0,q=L=w=null,x=u;do{var k=x.lane&-536870913,B=k!==x.lane;if(B?(Oe&k)===k:(s&k)===k){k!==0&&k===Ds&&(Au=!0),q!==null&&(q=q.next={lane:0,tag:x.tag,payload:x.payload,callback:null,next:null});e:{var ne=e,fe=x;k=t;var Ie=n;switch(fe.tag){case 1:if(ne=fe.payload,typeof ne=="function"){Q=ne.call(Ie,Q,k);break e}Q=ne;break e;case 3:ne.flags=ne.flags&-65537|128;case 0:if(ne=fe.payload,k=typeof ne=="function"?ne.call(Ie,Q,k):ne,k==null)break e;Q=y({},Q,k);break e;case 2:Zl=!0}}k=x.callback,k!==null&&(e.flags|=64,B&&(e.flags|=8192),B=o.callbacks,B===null?o.callbacks=[k]:B.push(k))}else B={lane:k,tag:x.tag,payload:x.payload,callback:x.callback,next:null},q===null?(L=q=B,w=Q):q=q.next=B,p|=k;if(x=x.next,x===null){if(x=o.shared.pending,x===null)break;B=x,x=B.next,B.next=null,o.lastBaseUpdate=B,o.shared.pending=null}}while(!0);q===null&&(w=Q),o.baseState=w,o.firstBaseUpdate=L,o.lastBaseUpdate=q,u===null&&(o.shared.lanes=0),na|=p,e.lanes=p,e.memoizedState=Q}}function Af(e,t){if(typeof e!="function")throw Error(r(191,e));e.call(t)}function Mf(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;eu?u:8;var p=U.T,x={};U.T=x,Zu(e,!1,t,n);try{var w=o(),L=U.S;if(L!==null&&L(x,w),w!==null&&typeof w=="object"&&typeof w.then=="function"){var q=b_(w,s);Wi(e,t,q,bn(e))}else Wi(e,t,s,bn(e))}catch(Q){Wi(e,t,{then:function(){},status:"rejected",reason:Q},bn())}finally{I.p=u,p!==null&&x.types!==null&&(p.types=x.types),U.T=p}}function E_(){}function Iu(e,t,n,s){if(e.tag!==5)throw Error(r(476));var o=oh(e).queue;rh(e,o,t,se,n===null?E_:function(){return uh(e),n(s)})}function oh(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:se,baseState:se,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:jl,lastRenderedState:se},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:jl,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function uh(e){var t=oh(e);t.next===null&&(t=e.alternate.memoizedState),Wi(e,t.next.queue,{},bn())}function Xu(){return zt(pc)}function dh(){return ft().memoizedState}function fh(){return ft().memoizedState}function T_(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=bn();e=Kl(n);var s=Pl(t,e,n);s!==null&&(an(s,t,n),Ii(s,t,n)),t={cache:Su()},e.payload=t;return}t=t.return}}function R_(e,t,n){var s=bn();n={lane:s,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},Er(e)?mh(t,n):(n=fu(e,t,n,s),n!==null&&(an(n,e,s),ph(n,t,s)))}function hh(e,t,n){var s=bn();Wi(e,t,n,s)}function Wi(e,t,n,s){var o={lane:s,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(Er(e))mh(t,o);else{var u=e.alternate;if(e.lanes===0&&(u===null||u.lanes===0)&&(u=t.lastRenderedReducer,u!==null))try{var p=t.lastRenderedState,x=u(p,n);if(o.hasEagerState=!0,o.eagerState=x,pn(x,p))return cr(e,t,o,0),Ze===null&&ir(),!1}catch{}finally{}if(n=fu(e,t,o,s),n!==null)return an(n,e,s),ph(n,t,s),!0}return!1}function Zu(e,t,n,s){if(s={lane:2,revertLane:E0(),gesture:null,action:s,hasEagerState:!1,eagerState:null,next:null},Er(e)){if(t)throw Error(r(479))}else t=fu(e,n,s,2),t!==null&&an(t,e,2)}function Er(e){var t=e.alternate;return e===xe||t!==null&&t===xe}function mh(e,t){Hs=xr=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function ph(e,t,n){if((n&4194048)!==0){var s=t.lanes;s&=e.pendingLanes,n|=s,t.lanes=n,y2(e,n)}}var Ji={readContext:zt,use:Sr,useCallback:ct,useContext:ct,useEffect:ct,useImperativeHandle:ct,useLayoutEffect:ct,useInsertionEffect:ct,useMemo:ct,useReducer:ct,useRef:ct,useState:ct,useDebugValue:ct,useDeferredValue:ct,useTransition:ct,useSyncExternalStore:ct,useId:ct,useHostTransitionStatus:ct,useFormState:ct,useActionState:ct,useOptimistic:ct,useMemoCache:ct,useCacheRefresh:ct};Ji.useEffectEvent=ct;var gh={readContext:zt,use:Sr,useCallback:function(e,t){return Gt().memoizedState=[e,t===void 0?null:t],e},useContext:zt,useEffect:Jf,useImperativeHandle:function(e,t,n){n=n!=null?n.concat([e]):null,wr(4194308,4,lh.bind(null,t,e),n)},useLayoutEffect:function(e,t){return wr(4194308,4,e,t)},useInsertionEffect:function(e,t){wr(4,2,e,t)},useMemo:function(e,t){var n=Gt();t=t===void 0?null:t;var s=e();if(Ga){Gl(!0);try{e()}finally{Gl(!1)}}return n.memoizedState=[s,t],s},useReducer:function(e,t,n){var s=Gt();if(n!==void 0){var o=n(t);if(Ga){Gl(!0);try{n(t)}finally{Gl(!1)}}}else o=t;return s.memoizedState=s.baseState=o,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:o},s.queue=e,e=e.dispatch=R_.bind(null,xe,e),[s.memoizedState,e]},useRef:function(e){var t=Gt();return e={current:e},t.memoizedState=e},useState:function(e){e=Gu(e);var t=e.queue,n=hh.bind(null,xe,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:Qu,useDeferredValue:function(e,t){var n=Gt();return Yu(n,e,t)},useTransition:function(){var e=Gu(!1);return e=rh.bind(null,xe,e.queue,!0,!1),Gt().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var s=xe,o=Gt();if(Le){if(n===void 0)throw Error(r(407));n=n()}else{if(n=t(),Ze===null)throw Error(r(349));(Oe&127)!==0||Bf(s,t,n)}o.memoizedState=n;var u={value:n,getSnapshot:t};return o.queue=u,Jf(Hf.bind(null,s,u,e),[e]),s.flags|=2048,qs(9,{destroy:void 0},Uf.bind(null,s,u,n,t),null),n},useId:function(){var e=Gt(),t=Ze.identifierPrefix;if(Le){var n=el,s=Jn;n=(s&~(1<<32-mn(s)-1)).toString(32)+n,t="_"+t+"R_"+n,n=br++,0<\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof s.is=="string"?p.createElement("select",{is:s.is}):p.createElement("select"),s.multiple?u.multiple=!0:s.size&&(u.size=s.size);break;default:u=typeof s.is=="string"?p.createElement(o,{is:s.is}):p.createElement(o)}}u[Mt]=t,u[Wt]=s;e:for(p=t.child;p!==null;){if(p.tag===5||p.tag===6)u.appendChild(p.stateNode);else if(p.tag!==4&&p.tag!==27&&p.child!==null){p.child.return=p,p=p.child;continue}if(p===t)break e;for(;p.sibling===null;){if(p.return===null||p.return===t)break e;p=p.return}p.sibling.return=p.return,p=p.sibling}t.stateNode=u;e:switch(Lt(u,o,s),o){case"button":case"input":case"select":case"textarea":s=!!s.autoFocus;break e;case"img":s=!0;break e;default:s=!1}s&&Nl(t)}}return tt(t),o0(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==s&&Nl(t);else{if(typeof s!="string"&&t.stateNode===null)throw Error(r(166));if(e=be.current,Os(t)){if(e=t.stateNode,n=t.memoizedProps,s=null,o=Ot,o!==null)switch(o.tag){case 27:case 5:s=o.memoizedProps}e[Mt]=t,e=!!(e.nodeValue===n||s!==null&&s.suppressHydrationWarning===!0||L1(e.nodeValue,n)),e||Il(t,!0)}else e=Ir(e).createTextNode(s),e[Mt]=t,t.stateNode=e}return tt(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(s=Os(t),n!==null){if(e===null){if(!s)throw Error(r(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(r(557));e[Mt]=t}else La(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;tt(t),e=!1}else n=yu(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(vn(t),t):(vn(t),null);if((t.flags&128)!==0)throw Error(r(558))}return tt(t),null;case 13:if(s=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(o=Os(t),s!==null&&s.dehydrated!==null){if(e===null){if(!o)throw Error(r(318));if(o=t.memoizedState,o=o!==null?o.dehydrated:null,!o)throw Error(r(317));o[Mt]=t}else La(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;tt(t),o=!1}else o=yu(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=o),o=!0;if(!o)return t.flags&256?(vn(t),t):(vn(t),null)}return vn(t),(t.flags&128)!==0?(t.lanes=n,t):(n=s!==null,e=e!==null&&e.memoizedState!==null,n&&(s=t.child,o=null,s.alternate!==null&&s.alternate.memoizedState!==null&&s.alternate.memoizedState.cachePool!==null&&(o=s.alternate.memoizedState.cachePool.pool),u=null,s.memoizedState!==null&&s.memoizedState.cachePool!==null&&(u=s.memoizedState.cachePool.pool),u!==o&&(s.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),Or(t,t.updateQueue),tt(t),null);case 4:return Je(),e===null&&M0(t.stateNode.containerInfo),tt(t),null;case 10:return xl(t.type),tt(t),null;case 19:if(V(dt),s=t.memoizedState,s===null)return tt(t),null;if(o=(t.flags&128)!==0,u=s.rendering,u===null)if(o)tc(s,!1);else{if(rt!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(u=yr(e),u!==null){for(t.flags|=128,tc(s,!1),e=u.updateQueue,t.updateQueue=e,Or(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)hf(n,e),n=n.sibling;return K(dt,dt.current&1|2),Le&&vl(t,s.treeForkCount),t.child}e=e.sibling}s.tail!==null&&fn()>Br&&(t.flags|=128,o=!0,tc(s,!1),t.lanes=4194304)}else{if(!o)if(e=yr(u),e!==null){if(t.flags|=128,o=!0,e=e.updateQueue,t.updateQueue=e,Or(t,e),tc(s,!0),s.tail===null&&s.tailMode==="hidden"&&!u.alternate&&!Le)return tt(t),null}else 2*fn()-s.renderingStartTime>Br&&n!==536870912&&(t.flags|=128,o=!0,tc(s,!1),t.lanes=4194304);s.isBackwards?(u.sibling=t.child,t.child=u):(e=s.last,e!==null?e.sibling=u:t.child=u,s.last=u)}return s.tail!==null?(e=s.tail,s.rendering=e,s.tail=e.sibling,s.renderingStartTime=fn(),e.sibling=null,n=dt.current,K(dt,o?n&1|2:n&1),Le&&vl(t,s.treeForkCount),e):(tt(t),null);case 22:case 23:return vn(t),Ou(),s=t.memoizedState!==null,e!==null?e.memoizedState!==null!==s&&(t.flags|=8192):s&&(t.flags|=8192),s?(n&536870912)!==0&&(t.flags&128)===0&&(tt(t),t.subtreeFlags&6&&(t.flags|=8192)):tt(t),n=t.updateQueue,n!==null&&Or(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),s=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(s=t.memoizedState.cachePool.pool),s!==n&&(t.flags|=2048),e!==null&&V(Ua),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),xl(gt),tt(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function D_(e,t){switch(_u(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return xl(gt),Je(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return fl(t),null;case 31:if(t.memoizedState!==null){if(vn(t),t.alternate===null)throw Error(r(340));La()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(vn(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(r(340));La()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return V(dt),null;case 4:return Je(),null;case 10:return xl(t.type),null;case 22:case 23:return vn(t),Ou(),e!==null&&V(Ua),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return xl(gt),null;case 25:return null;default:return null}}function $h(e,t){switch(_u(t),t.tag){case 3:xl(gt),Je();break;case 26:case 27:case 5:fl(t);break;case 4:Je();break;case 31:t.memoizedState!==null&&vn(t);break;case 13:vn(t);break;case 19:V(dt);break;case 10:xl(t.type);break;case 22:case 23:vn(t),Ou(),e!==null&&V(Ua);break;case 24:xl(gt)}}function nc(e,t){try{var n=t.updateQueue,s=n!==null?n.lastEffect:null;if(s!==null){var o=s.next;n=o;do{if((n.tag&e)===e){s=void 0;var u=n.create,p=n.inst;s=u(),p.destroy=s}n=n.next}while(n!==o)}}catch(x){Fe(t,t.return,x)}}function ea(e,t,n){try{var s=t.updateQueue,o=s!==null?s.lastEffect:null;if(o!==null){var u=o.next;s=u;do{if((s.tag&e)===e){var p=s.inst,x=p.destroy;if(x!==void 0){p.destroy=void 0,o=t;var w=n,L=x;try{L()}catch(q){Fe(o,w,q)}}}s=s.next}while(s!==u)}}catch(q){Fe(t,t.return,q)}}function qh(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{Mf(t,n)}catch(s){Fe(e,e.return,s)}}}function Gh(e,t,n){n.props=Fa(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(s){Fe(e,t,s)}}function lc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var s=e.stateNode;break;case 30:s=e.stateNode;break;default:s=e.stateNode}typeof n=="function"?e.refCleanup=n(s):n.current=s}}catch(o){Fe(e,t,o)}}function tl(e,t){var n=e.ref,s=e.refCleanup;if(n!==null)if(typeof s=="function")try{s()}catch(o){Fe(e,t,o)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n=="function")try{n(null)}catch(o){Fe(e,t,o)}else n.current=null}function Fh(e){var t=e.type,n=e.memoizedProps,s=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":n.autoFocus&&s.focus();break e;case"img":n.src?s.src=n.src:n.srcSet&&(s.srcset=n.srcSet)}}catch(o){Fe(e,e.return,o)}}function u0(e,t,n){try{var s=e.stateNode;nv(s,e.type,n,t),s[Wt]=t}catch(o){Fe(e,e.return,o)}}function Vh(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&ca(e.type)||e.tag===4}function d0(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Vh(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&ca(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function f0(e,t,n){var s=e.tag;if(s===5||s===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName==="HTML"?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName==="HTML"?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=pl));else if(s!==4&&(s===27&&ca(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(f0(e,t,n),e=e.sibling;e!==null;)f0(e,t,n),e=e.sibling}function zr(e,t,n){var s=e.tag;if(s===5||s===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(s!==4&&(s===27&&ca(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(zr(e,t,n),e=e.sibling;e!==null;)zr(e,t,n),e=e.sibling}function Qh(e){var t=e.stateNode,n=e.memoizedProps;try{for(var s=e.type,o=t.attributes;o.length;)t.removeAttributeNode(o[0]);Lt(t,s,n),t[Mt]=e,t[Wt]=n}catch(u){Fe(e,e.return,u)}}var wl=!1,yt=!1,h0=!1,Yh=typeof WeakSet=="function"?WeakSet:Set,Et=null;function L_(e,t){if(e=e.containerInfo,D0=eo,e=lf(e),iu(e)){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{n=(n=e.ownerDocument)&&n.defaultView||window;var s=n.getSelection&&n.getSelection();if(s&&s.rangeCount!==0){n=s.anchorNode;var o=s.anchorOffset,u=s.focusNode;s=s.focusOffset;try{n.nodeType,u.nodeType}catch{n=null;break e}var p=0,x=-1,w=-1,L=0,q=0,Q=e,k=null;t:for(;;){for(var B;Q!==n||o!==0&&Q.nodeType!==3||(x=p+o),Q!==u||s!==0&&Q.nodeType!==3||(w=p+s),Q.nodeType===3&&(p+=Q.nodeValue.length),(B=Q.firstChild)!==null;)k=Q,Q=B;for(;;){if(Q===e)break t;if(k===n&&++L===o&&(x=p),k===u&&++q===s&&(w=p),(B=Q.nextSibling)!==null)break;Q=k,k=Q.parentNode}Q=B}n=x===-1||w===-1?null:{start:x,end:w}}else n=null}n=n||{start:0,end:0}}else n=null;for(L0={focusedElem:e,selectionRange:n},eo=!1,Et=t;Et!==null;)if(t=Et,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,Et=e;else for(;Et!==null;){switch(t=Et,u=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(n=0;n title"))),Lt(u,s,n),u[Mt]=e,Ct(u),s=u;break e;case"link":var p=W1("link","href",o).get(s+(n.href||""));if(p){for(var x=0;xIe&&(p=Ie,Ie=fe,fe=p);var M=tf(x,fe),A=tf(x,Ie);if(M&&A&&(B.rangeCount!==1||B.anchorNode!==M.node||B.anchorOffset!==M.offset||B.focusNode!==A.node||B.focusOffset!==A.offset)){var D=Q.createRange();D.setStart(M.node,M.offset),B.removeAllRanges(),fe>Ie?(B.addRange(D),B.extend(A.node,A.offset)):(D.setEnd(A.node,A.offset),B.addRange(D))}}}}for(Q=[],B=x;B=B.parentNode;)B.nodeType===1&&Q.push({element:B,left:B.scrollLeft,top:B.scrollTop});for(typeof x.focus=="function"&&x.focus(),x=0;xn?32:n,U.T=null,n=x0,x0=null;var u=aa,p=Al;if(St=0,Ys=aa=null,Al=0,($e&6)!==0)throw Error(r(331));var x=$e;if($e|=4,l1(u.current),e1(u,u.current,p,n),$e=x,oc(0,!1),hn&&typeof hn.onPostCommitFiberRoot=="function")try{hn.onPostCommitFiberRoot(Ei,u)}catch{}return!0}finally{I.p=o,U.T=s,b1(e,t)}}function S1(e,t,n){t=zn(n,t),t=Ju(e.stateNode,t,2),e=Pl(e,t,2),e!==null&&(Ri(e,2),nl(e))}function Fe(e,t,n){if(e.tag===3)S1(e,e,n);else for(;t!==null;){if(t.tag===3){S1(t,e,n);break}else if(t.tag===1){var s=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof s.componentDidCatch=="function"&&(la===null||!la.has(s))){e=zn(n,e),n=Nh(2),s=Pl(t,n,2),s!==null&&(wh(n,s,t,e),Ri(s,2),nl(s));break}}t=t.return}}function N0(e,t,n){var s=e.pingCache;if(s===null){s=e.pingCache=new U_;var o=new Set;s.set(t,o)}else o=s.get(t),o===void 0&&(o=new Set,s.set(t,o));o.has(n)||(g0=!0,o.add(n),e=F_.bind(null,e,t,n),t.then(e,e))}function F_(e,t,n){var s=e.pingCache;s!==null&&s.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,Ze===e&&(Oe&n)===n&&(rt===4||rt===3&&(Oe&62914560)===Oe&&300>fn()-kr?($e&2)===0&&Is(e,0):_0|=n,Qs===Oe&&(Qs=0)),nl(e)}function N1(e,t){t===0&&(t=_2()),e=za(e,t),e!==null&&(Ri(e,t),nl(e))}function V_(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),N1(e,n)}function Q_(e,t){var n=0;switch(e.tag){case 31:case 13:var s=e.stateNode,o=e.memoizedState;o!==null&&(n=o.retryLane);break;case 19:s=e.stateNode;break;case 22:s=e.stateNode._retryCache;break;default:throw Error(r(314))}s!==null&&s.delete(t),N1(e,n)}function Y_(e,t){return ps(e,t)}var Fr=null,Zs=null,w0=!1,Vr=!1,C0=!1,ia=0;function nl(e){e!==Zs&&e.next===null&&(Zs===null?Fr=Zs=e:Zs=Zs.next=e),Vr=!0,w0||(w0=!0,X_())}function oc(e,t){if(!C0&&Vr){C0=!0;do for(var n=!1,s=Fr;s!==null;){if(e!==0){var o=s.pendingLanes;if(o===0)var u=0;else{var p=s.suspendedLanes,x=s.pingedLanes;u=(1<<31-mn(42|e)+1)-1,u&=o&~(p&~x),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(n=!0,T1(s,u))}else u=Oe,u=Xc(s,s===Ze?u:0,s.cancelPendingCommit!==null||s.timeoutHandle!==-1),(u&3)===0||Ti(s,u)||(n=!0,T1(s,u));s=s.next}while(n);C0=!1}}function I_(){w1()}function w1(){Vr=w0=!1;var e=0;ia!==0&&av()&&(e=ia);for(var t=fn(),n=null,s=Fr;s!==null;){var o=s.next,u=C1(s,t);u===0?(s.next=null,n===null?Fr=o:n.next=o,o===null&&(Zs=n)):(n=s,(e!==0||(u&3)!==0)&&(Vr=!0)),s=o}St!==0&&St!==5||oc(e),ia!==0&&(ia=0)}function C1(e,t){for(var n=e.suspendedLanes,s=e.pingedLanes,o=e.expirationTimes,u=e.pendingLanes&-62914561;0x)break;var q=w.transferSize,Q=w.initiatorType;q&&k1(Q)&&(w=w.responseEnd,p+=q*(w"u"?null:document;function X1(e,t,n){var s=Ks;if(s&&typeof t=="string"&&t){var o=Mn(t);o='link[rel="'+e+'"][href="'+o+'"]',typeof n=="string"&&(o+='[crossorigin="'+n+'"]'),I1.has(o)||(I1.add(o),e={rel:e,crossOrigin:n,href:t},s.querySelector(o)===null&&(t=s.createElement("link"),Lt(t,"link",e),Ct(t),s.head.appendChild(t)))}}function hv(e){Ml.D(e),X1("dns-prefetch",e,null)}function mv(e,t){Ml.C(e,t),X1("preconnect",e,t)}function pv(e,t,n){Ml.L(e,t,n);var s=Ks;if(s&&e&&t){var o='link[rel="preload"][as="'+Mn(t)+'"]';t==="image"&&n&&n.imageSrcSet?(o+='[imagesrcset="'+Mn(n.imageSrcSet)+'"]',typeof n.imageSizes=="string"&&(o+='[imagesizes="'+Mn(n.imageSizes)+'"]')):o+='[href="'+Mn(e)+'"]';var u=o;switch(t){case"style":u=Ps(e);break;case"script":u=Ws(e)}Hn.has(u)||(e=y({rel:"preload",href:t==="image"&&n&&n.imageSrcSet?void 0:e,as:t},n),Hn.set(u,e),s.querySelector(o)!==null||t==="style"&&s.querySelector(hc(u))||t==="script"&&s.querySelector(mc(u))||(t=s.createElement("link"),Lt(t,"link",e),Ct(t),s.head.appendChild(t)))}}function gv(e,t){Ml.m(e,t);var n=Ks;if(n&&e){var s=t&&typeof t.as=="string"?t.as:"script",o='link[rel="modulepreload"][as="'+Mn(s)+'"][href="'+Mn(e)+'"]',u=o;switch(s){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=Ws(e)}if(!Hn.has(u)&&(e=y({rel:"modulepreload",href:e},t),Hn.set(u,e),n.querySelector(o)===null)){switch(s){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(n.querySelector(mc(u)))return}s=n.createElement("link"),Lt(s,"link",e),Ct(s),n.head.appendChild(s)}}}function _v(e,t,n){Ml.S(e,t,n);var s=Ks;if(s&&e){var o=ys(s).hoistableStyles,u=Ps(e);t=t||"default";var p=o.get(u);if(!p){var x={loading:0,preload:null};if(p=s.querySelector(hc(u)))x.loading=5;else{e=y({rel:"stylesheet",href:e,"data-precedence":t},n),(n=Hn.get(u))&&G0(e,n);var w=p=s.createElement("link");Ct(w),Lt(w,"link",e),w._p=new Promise(function(L,q){w.onload=L,w.onerror=q}),w.addEventListener("load",function(){x.loading|=1}),w.addEventListener("error",function(){x.loading|=2}),x.loading|=4,Zr(p,t,s)}p={type:"stylesheet",instance:p,count:1,state:x},o.set(u,p)}}}function vv(e,t){Ml.X(e,t);var n=Ks;if(n&&e){var s=ys(n).hoistableScripts,o=Ws(e),u=s.get(o);u||(u=n.querySelector(mc(o)),u||(e=y({src:e,async:!0},t),(t=Hn.get(o))&&F0(e,t),u=n.createElement("script"),Ct(u),Lt(u,"link",e),n.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},s.set(o,u))}}function yv(e,t){Ml.M(e,t);var n=Ks;if(n&&e){var s=ys(n).hoistableScripts,o=Ws(e),u=s.get(o);u||(u=n.querySelector(mc(o)),u||(e=y({src:e,async:!0,type:"module"},t),(t=Hn.get(o))&&F0(e,t),u=n.createElement("script"),Ct(u),Lt(u,"link",e),n.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},s.set(o,u))}}function Z1(e,t,n,s){var o=(o=be.current)?Xr(o):null;if(!o)throw Error(r(446));switch(e){case"meta":case"title":return null;case"style":return typeof n.precedence=="string"&&typeof n.href=="string"?(t=Ps(n.href),n=ys(o).hoistableStyles,s=n.get(t),s||(s={type:"style",instance:null,count:0,state:null},n.set(t,s)),s):{type:"void",instance:null,count:0,state:null};case"link":if(n.rel==="stylesheet"&&typeof n.href=="string"&&typeof n.precedence=="string"){e=Ps(n.href);var u=ys(o).hoistableStyles,p=u.get(e);if(p||(o=o.ownerDocument||o,p={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(e,p),(u=o.querySelector(hc(e)))&&!u._p&&(p.instance=u,p.state.loading=5),Hn.has(e)||(n={rel:"preload",as:"style",href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},Hn.set(e,n),u||xv(o,e,n,p.state))),t&&s===null)throw Error(r(528,""));return p}if(t&&s!==null)throw Error(r(529,""));return null;case"script":return t=n.async,n=n.src,typeof n=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=Ws(n),n=ys(o).hoistableScripts,s=n.get(t),s||(s={type:"script",instance:null,count:0,state:null},n.set(t,s)),s):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,e))}}function Ps(e){return'href="'+Mn(e)+'"'}function hc(e){return'link[rel="stylesheet"]['+e+"]"}function K1(e){return y({},e,{"data-precedence":e.precedence,precedence:null})}function xv(e,t,n,s){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?s.loading=1:(t=e.createElement("link"),s.preload=t,t.addEventListener("load",function(){return s.loading|=1}),t.addEventListener("error",function(){return s.loading|=2}),Lt(t,"link",n),Ct(t),e.head.appendChild(t))}function Ws(e){return'[src="'+Mn(e)+'"]'}function mc(e){return"script[async]"+e}function P1(e,t,n){if(t.count++,t.instance===null)switch(t.type){case"style":var s=e.querySelector('style[data-href~="'+Mn(n.href)+'"]');if(s)return t.instance=s,Ct(s),s;var o=y({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return s=(e.ownerDocument||e).createElement("style"),Ct(s),Lt(s,"style",o),Zr(s,n.precedence,e),t.instance=s;case"stylesheet":o=Ps(n.href);var u=e.querySelector(hc(o));if(u)return t.state.loading|=4,t.instance=u,Ct(u),u;s=K1(n),(o=Hn.get(o))&&G0(s,o),u=(e.ownerDocument||e).createElement("link"),Ct(u);var p=u;return p._p=new Promise(function(x,w){p.onload=x,p.onerror=w}),Lt(u,"link",s),t.state.loading|=4,Zr(u,n.precedence,e),t.instance=u;case"script":return u=Ws(n.src),(o=e.querySelector(mc(u)))?(t.instance=o,Ct(o),o):(s=n,(o=Hn.get(u))&&(s=y({},n),F0(s,o)),e=e.ownerDocument||e,o=e.createElement("script"),Ct(o),Lt(o,"link",s),e.head.appendChild(o),t.instance=o);case"void":return null;default:throw Error(r(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(s=t.instance,t.state.loading|=4,Zr(s,n.precedence,e));return t.instance}function Zr(e,t,n){for(var s=n.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),o=s.length?s[s.length-1]:null,u=o,p=0;p title"):null)}function bv(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;switch(t.rel){case"stylesheet":return e=t.disabled,typeof t.precedence=="string"&&e==null;default:return!0}case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function em(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function jv(e,t,n,s){if(n.type==="stylesheet"&&(typeof s.media!="string"||matchMedia(s.media).matches!==!1)&&(n.state.loading&4)===0){if(n.instance===null){var o=Ps(s.href),u=t.querySelector(hc(o));if(u){t=u._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=Pr.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=u,Ct(u);return}u=t.ownerDocument||t,s=K1(s),(o=Hn.get(o))&&G0(s,o),u=u.createElement("link"),Ct(u);var p=u;p._p=new Promise(function(x,w){p.onload=x,p.onerror=w}),Lt(u,"link",s),n.instance=u}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&(n.state.loading&3)===0&&(e.count++,n=Pr.bind(e),t.addEventListener("load",n),t.addEventListener("error",n))}}var V0=0;function Sv(e,t){return e.stylesheets&&e.count===0&&Jr(e,e.stylesheets),0V0?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(s),clearTimeout(o)}}:null}function Pr(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Jr(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Wr=null;function Jr(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Wr=new Map,t.forEach(Nv,e),Wr=null,Pr.call(e))}function Nv(e,t){if(!(t.state.loading&4)){var n=Wr.get(e);if(n)var s=n.get(null);else{n=new Map,Wr.set(e,n);for(var o=e.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(a)}catch(i){console.error(i)}}return a(),ed.exports=$v(),ed.exports}var Gv=qv();/** + * react-router v7.14.2 + * + * Copyright (c) Remix Software Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE.md file in the root directory of this source tree. + * + * @license MIT + */var wm="popstate";function Cm(a){return typeof a=="object"&&a!=null&&"pathname"in a&&"search"in a&&"hash"in a&&"state"in a&&"key"in a}function Fv(a={}){function i(r,d){var m;let f=(m=d.state)==null?void 0:m.masked,{pathname:g,search:v,hash:h}=f||r.location;return Sd("",{pathname:g,search:v,hash:h},d.state&&d.state.usr||null,d.state&&d.state.key||"default",f?{pathname:r.location.pathname,search:r.location.search,hash:r.location.hash}:void 0)}function c(r,d){return typeof d=="string"?d:Ac(d)}return Qv(i,c,null,a)}function at(a,i){if(a===!1||a===null||typeof a>"u")throw new Error(i)}function Kn(a,i){if(!a){typeof console<"u"&&console.warn(i);try{throw new Error(i)}catch{}}}function Vv(){return Math.random().toString(36).substring(2,10)}function Em(a,i){return{usr:a.state,key:a.key,idx:i,masked:a.unstable_mask?{pathname:a.pathname,search:a.search,hash:a.hash}:void 0}}function Sd(a,i,c=null,r,d){return{pathname:typeof a=="string"?a:a.pathname,search:"",hash:"",...typeof i=="string"?yi(i):i,state:c,key:i&&i.key||r||Vv(),unstable_mask:d}}function Ac({pathname:a="/",search:i="",hash:c=""}){return i&&i!=="?"&&(a+=i.charAt(0)==="?"?i:"?"+i),c&&c!=="#"&&(a+=c.charAt(0)==="#"?c:"#"+c),a}function yi(a){let i={};if(a){let c=a.indexOf("#");c>=0&&(i.hash=a.substring(c),a=a.substring(0,c));let r=a.indexOf("?");r>=0&&(i.search=a.substring(r),a=a.substring(0,r)),a&&(i.pathname=a)}return i}function Qv(a,i,c,r={}){let{window:d=document.defaultView,v5Compat:f=!1}=r,g=d.history,v="POP",h=null,m=_();m==null&&(m=0,g.replaceState({...g.state,idx:m},""));function _(){return(g.state||{idx:null}).idx}function y(){v="POP";let T=_(),O=T==null?null:T-m;m=T,h&&h({action:v,location:E.location,delta:O})}function b(T,O){v="PUSH";let H=Cm(T)?T:Sd(E.location,T,O);m=_()+1;let z=Em(H,m),G=E.createHref(H.unstable_mask||H);try{g.pushState(z,"",G)}catch(Y){if(Y instanceof DOMException&&Y.name==="DataCloneError")throw Y;d.location.assign(G)}f&&h&&h({action:v,location:E.location,delta:1})}function N(T,O){v="REPLACE";let H=Cm(T)?T:Sd(E.location,T,O);m=_();let z=Em(H,m),G=E.createHref(H.unstable_mask||H);g.replaceState(z,"",G),f&&h&&h({action:v,location:E.location,delta:0})}function S(T){return Yv(T)}let E={get action(){return v},get location(){return a(d,g)},listen(T){if(h)throw new Error("A history only accepts one active listener");return d.addEventListener(wm,y),h=T,()=>{d.removeEventListener(wm,y),h=null}},createHref(T){return i(d,T)},createURL:S,encodeLocation(T){let O=S(T);return{pathname:O.pathname,search:O.search,hash:O.hash}},push:b,replace:N,go(T){return g.go(T)}};return E}function Yv(a,i=!1){let c="http://localhost";typeof window<"u"&&(c=window.location.origin!=="null"?window.location.origin:window.location.href),at(c,"No window.location.(origin|href) available to create URL");let r=typeof a=="string"?a:Ac(a);return r=r.replace(/ $/,"%20"),!i&&r.startsWith("//")&&(r=c+r),new URL(r,c)}function Fp(a,i,c="/"){return Iv(a,i,c,!1)}function Iv(a,i,c,r){let d=typeof i=="string"?yi(i):i,f=Hl(d.pathname||"/",c);if(f==null)return null;let g=Vp(a);Xv(g);let v=null;for(let h=0;v==null&&h{let _={relativePath:m===void 0?g.path||"":m,caseSensitive:g.caseSensitive===!0,childrenIndex:v,route:g};if(_.relativePath.startsWith("/")){if(!_.relativePath.startsWith(r)&&h)return;at(_.relativePath.startsWith(r),`Absolute route path "${_.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),_.relativePath=_.relativePath.slice(r.length)}let y=Zn([r,_.relativePath]),b=c.concat(_);g.children&&g.children.length>0&&(at(g.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${y}".`),Vp(g.children,i,b,y,h)),!(g.path==null&&!g.index)&&i.push({path:y,score:ty(y,g.index),routesMeta:b})};return a.forEach((g,v)=>{var h;if(g.path===""||!((h=g.path)!=null&&h.includes("?")))f(g,v);else for(let m of Qp(g.path))f(g,v,!0,m)}),i}function Qp(a){let i=a.split("/");if(i.length===0)return[];let[c,...r]=i,d=c.endsWith("?"),f=c.replace(/\?$/,"");if(r.length===0)return d?[f,""]:[f];let g=Qp(r.join("/")),v=[];return v.push(...g.map(h=>h===""?f:[f,h].join("/"))),d&&v.push(...g),v.map(h=>a.startsWith("/")&&h===""?"/":h)}function Xv(a){a.sort((i,c)=>i.score!==c.score?c.score-i.score:ny(i.routesMeta.map(r=>r.childrenIndex),c.routesMeta.map(r=>r.childrenIndex)))}var Zv=/^:[\w-]+$/,Kv=3,Pv=2,Wv=1,Jv=10,ey=-2,Tm=a=>a==="*";function ty(a,i){let c=a.split("/"),r=c.length;return c.some(Tm)&&(r+=ey),i&&(r+=Pv),c.filter(d=>!Tm(d)).reduce((d,f)=>d+(Zv.test(f)?Kv:f===""?Wv:Jv),r)}function ny(a,i){return a.length===i.length&&a.slice(0,-1).every((r,d)=>r===i[d])?a[a.length-1]-i[i.length-1]:0}function ly(a,i,c=!1){let{routesMeta:r}=a,d={},f="/",g=[];for(let v=0;v{if(_==="*"){let S=v[b]||"";g=f.slice(0,f.length-S.length).replace(/(.)\/+$/,"$1")}const N=v[b];return y&&!N?m[_]=void 0:m[_]=(N||"").replace(/%2F/g,"/"),m},{}),pathname:f,pathnameBase:g,pattern:a}}function ay(a,i=!1,c=!0){Kn(a==="*"||!a.endsWith("*")||a.endsWith("/*"),`Route path "${a}" will be treated as if it were "${a.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${a.replace(/\*$/,"/*")}".`);let r=[],d="^"+a.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(g,v,h,m,_)=>{if(r.push({paramName:v,isOptional:h!=null}),h){let y=_.charAt(m+g.length);return y&&y!=="/"?"/([^\\/]*)":"(?:/([^\\/]*))?"}return"/([^\\/]+)"}).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return a.endsWith("*")?(r.push({paramName:"*"}),d+=a==="*"||a==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):c?d+="\\/*$":a!==""&&a!=="/"&&(d+="(?:(?=\\/|$))"),[new RegExp(d,i?void 0:"i"),r]}function sy(a){try{return a.split("/").map(i=>decodeURIComponent(i).replace(/\//g,"%2F")).join("/")}catch(i){return Kn(!1,`The URL path "${a}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${i}).`),a}}function Hl(a,i){if(i==="/")return a;if(!a.toLowerCase().startsWith(i.toLowerCase()))return null;let c=i.endsWith("/")?i.length-1:i.length,r=a.charAt(c);return r&&r!=="/"?null:a.slice(c)||"/"}var iy=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function cy(a,i="/"){let{pathname:c,search:r="",hash:d=""}=typeof a=="string"?yi(a):a,f;return c?(c=Yp(c),c.startsWith("/")?f=Rm(c.substring(1),"/"):f=Rm(c,i)):f=i,{pathname:f,search:uy(r),hash:dy(d)}}function Rm(a,i){let c=xo(i).split("/");return a.split("/").forEach(d=>{d===".."?c.length>1&&c.pop():d!=="."&&c.push(d)}),c.length>1?c.join("/"):"/"}function ad(a,i,c,r){return`Cannot include a '${a}' character in a manually specified \`to.${i}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${c}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function ry(a){return a.filter((i,c)=>c===0||i.route.path&&i.route.path.length>0)}function Pd(a){let i=ry(a);return i.map((c,r)=>r===i.length-1?c.pathname:c.pathnameBase)}function Ro(a,i,c,r=!1){let d;typeof a=="string"?d=yi(a):(d={...a},at(!d.pathname||!d.pathname.includes("?"),ad("?","pathname","search",d)),at(!d.pathname||!d.pathname.includes("#"),ad("#","pathname","hash",d)),at(!d.search||!d.search.includes("#"),ad("#","search","hash",d)));let f=a===""||d.pathname==="",g=f?"/":d.pathname,v;if(g==null)v=c;else{let y=i.length-1;if(!r&&g.startsWith("..")){let b=g.split("/");for(;b[0]==="..";)b.shift(),y-=1;d.pathname=b.join("/")}v=y>=0?i[y]:"/"}let h=cy(d,v),m=g&&g!=="/"&&g.endsWith("/"),_=(f||g===".")&&c.endsWith("/");return!h.pathname.endsWith("/")&&(m||_)&&(h.pathname+="/"),h}var Yp=a=>a.replace(/\/\/+/g,"/"),Zn=a=>Yp(a.join("/")),xo=a=>a.replace(/\/+$/,""),oy=a=>xo(a).replace(/^\/*/,"/"),uy=a=>!a||a==="?"?"":a.startsWith("?")?a:"?"+a,dy=a=>!a||a==="#"?"":a.startsWith("#")?a:"#"+a,fy=class{constructor(a,i,c,r=!1){this.status=a,this.statusText=i||"",this.internal=r,c instanceof Error?(this.data=c.toString(),this.error=c):this.data=c}};function hy(a){return a!=null&&typeof a.status=="number"&&typeof a.statusText=="string"&&typeof a.internal=="boolean"&&"data"in a}function my(a){let i=a.map(c=>c.route.path).filter(Boolean);return Zn(i)||"/"}var Ip=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function Xp(a,i){let c=a;if(typeof c!="string"||!iy.test(c))return{absoluteURL:void 0,isExternal:!1,to:c};let r=c,d=!1;if(Ip)try{let f=new URL(window.location.href),g=c.startsWith("//")?new URL(f.protocol+c):new URL(c),v=Hl(g.pathname,i);g.origin===f.origin&&v!=null?c=v+g.search+g.hash:d=!0}catch{Kn(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:r,isExternal:d,to:c}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var Zp=["POST","PUT","PATCH","DELETE"];new Set(Zp);var py=["GET",...Zp];new Set(py);var xi=j.createContext(null);xi.displayName="DataRouter";var Ao=j.createContext(null);Ao.displayName="DataRouterState";var Kp=j.createContext(!1);function gy(){return j.useContext(Kp)}var Pp=j.createContext({isTransitioning:!1});Pp.displayName="ViewTransition";var _y=j.createContext(new Map);_y.displayName="Fetchers";var vy=j.createContext(null);vy.displayName="Await";var Cn=j.createContext(null);Cn.displayName="Navigation";var Hc=j.createContext(null);Hc.displayName="Location";var Vn=j.createContext({outlet:null,matches:[],isDataRoute:!1});Vn.displayName="Route";var Wd=j.createContext(null);Wd.displayName="RouteError";var Wp="REACT_ROUTER_ERROR",yy="REDIRECT",xy="ROUTE_ERROR_RESPONSE";function by(a){if(a.startsWith(`${Wp}:${yy}:{`))try{let i=JSON.parse(a.slice(28));if(typeof i=="object"&&i&&typeof i.status=="number"&&typeof i.statusText=="string"&&typeof i.location=="string"&&typeof i.reloadDocument=="boolean"&&typeof i.replace=="boolean")return i}catch{}}function jy(a){if(a.startsWith(`${Wp}:${xy}:{`))try{let i=JSON.parse(a.slice(40));if(typeof i=="object"&&i&&typeof i.status=="number"&&typeof i.statusText=="string")return new fy(i.status,i.statusText,i.data)}catch{}}function Sy(a,{relative:i}={}){at(bi(),"useHref() may be used only in the context of a component.");let{basename:c,navigator:r}=j.useContext(Cn),{hash:d,pathname:f,search:g}=$c(a,{relative:i}),v=f;return c!=="/"&&(v=f==="/"?c:Zn([c,f])),r.createHref({pathname:v,search:g,hash:d})}function bi(){return j.useContext(Hc)!=null}function En(){return at(bi(),"useLocation() may be used only in the context of a component."),j.useContext(Hc).location}var Jp="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function e3(a){j.useContext(Cn).static||j.useLayoutEffect(a)}function Tn(){let{isDataRoute:a}=j.useContext(Vn);return a?Hy():Ny()}function Ny(){at(bi(),"useNavigate() may be used only in the context of a component.");let a=j.useContext(xi),{basename:i,navigator:c}=j.useContext(Cn),{matches:r}=j.useContext(Vn),{pathname:d}=En(),f=JSON.stringify(Pd(r)),g=j.useRef(!1);return e3(()=>{g.current=!0}),j.useCallback((h,m={})=>{if(Kn(g.current,Jp),!g.current)return;if(typeof h=="number"){c.go(h);return}let _=Ro(h,JSON.parse(f),d,m.relative==="path");a==null&&i!=="/"&&(_.pathname=_.pathname==="/"?i:Zn([i,_.pathname])),(m.replace?c.replace:c.push)(_,m.state,m)},[i,c,f,d,a])}var wy=j.createContext(null);function Cy(a){let i=j.useContext(Vn).outlet;return j.useMemo(()=>i&&j.createElement(wy.Provider,{value:a},i),[i,a])}function Ey(){let{matches:a}=j.useContext(Vn),i=a[a.length-1];return(i==null?void 0:i.params)??{}}function $c(a,{relative:i}={}){let{matches:c}=j.useContext(Vn),{pathname:r}=En(),d=JSON.stringify(Pd(c));return j.useMemo(()=>Ro(a,JSON.parse(d),r,i==="path"),[a,d,r,i])}function Ty(a,i){return t3(a,i)}function t3(a,i,c){var T;at(bi(),"useRoutes() may be used only in the context of a component.");let{navigator:r}=j.useContext(Cn),{matches:d}=j.useContext(Vn),f=d[d.length-1],g=f?f.params:{},v=f?f.pathname:"/",h=f?f.pathnameBase:"/",m=f&&f.route;{let O=m&&m.path||"";l3(v,!m||O.endsWith("*")||O.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${v}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. + +Please change the parent to .`)}let _=En(),y;if(i){let O=typeof i=="string"?yi(i):i;at(h==="/"||((T=O.pathname)==null?void 0:T.startsWith(h)),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${h}" but pathname "${O.pathname}" was given in the \`location\` prop.`),y=O}else y=_;let b=y.pathname||"/",N=b;if(h!=="/"){let O=h.replace(/^\//,"").split("/");N="/"+b.replace(/^\//,"").split("/").slice(O.length).join("/")}let S=Fp(a,{pathname:N});Kn(m||S!=null,`No routes matched location "${y.pathname}${y.search}${y.hash}" `),Kn(S==null||S[S.length-1].route.element!==void 0||S[S.length-1].route.Component!==void 0||S[S.length-1].route.lazy!==void 0,`Matched leaf route at location "${y.pathname}${y.search}${y.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let E=zy(S&&S.map(O=>Object.assign({},O,{params:Object.assign({},g,O.params),pathname:Zn([h,r.encodeLocation?r.encodeLocation(O.pathname.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:O.pathname]),pathnameBase:O.pathnameBase==="/"?h:Zn([h,r.encodeLocation?r.encodeLocation(O.pathnameBase.replace(/%/g,"%25").replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:O.pathnameBase])})),d,c);return i&&E?j.createElement(Hc.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",unstable_mask:void 0,...y},navigationType:"POP"}},E):E}function Ry(){let a=Uy(),i=hy(a)?`${a.status} ${a.statusText}`:a instanceof Error?a.message:JSON.stringify(a),c=a instanceof Error?a.stack:null,r="rgba(200,200,200, 0.5)",d={padding:"0.5rem",backgroundColor:r},f={padding:"2px 4px",backgroundColor:r},g=null;return console.error("Error handled by React Router default ErrorBoundary:",a),g=j.createElement(j.Fragment,null,j.createElement("p",null,"💿 Hey developer 👋"),j.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",j.createElement("code",{style:f},"ErrorBoundary")," or"," ",j.createElement("code",{style:f},"errorElement")," prop on your route.")),j.createElement(j.Fragment,null,j.createElement("h2",null,"Unexpected Application Error!"),j.createElement("h3",{style:{fontStyle:"italic"}},i),c?j.createElement("pre",{style:d},c):null,g)}var Ay=j.createElement(Ry,null),n3=class extends j.Component{constructor(a){super(a),this.state={location:a.location,revalidation:a.revalidation,error:a.error}}static getDerivedStateFromError(a){return{error:a}}static getDerivedStateFromProps(a,i){return i.location!==a.location||i.revalidation!=="idle"&&a.revalidation==="idle"?{error:a.error,location:a.location,revalidation:a.revalidation}:{error:a.error!==void 0?a.error:i.error,location:i.location,revalidation:a.revalidation||i.revalidation}}componentDidCatch(a,i){this.props.onError?this.props.onError(a,i):console.error("React Router caught the following error during render",a)}render(){let a=this.state.error;if(this.context&&typeof a=="object"&&a&&"digest"in a&&typeof a.digest=="string"){const c=jy(a.digest);c&&(a=c)}let i=a!==void 0?j.createElement(Vn.Provider,{value:this.props.routeContext},j.createElement(Wd.Provider,{value:a,children:this.props.component})):this.props.children;return this.context?j.createElement(My,{error:a},i):i}};n3.contextType=Kp;var sd=new WeakMap;function My({children:a,error:i}){let{basename:c}=j.useContext(Cn);if(typeof i=="object"&&i&&"digest"in i&&typeof i.digest=="string"){let r=by(i.digest);if(r){let d=sd.get(i);if(d)throw d;let f=Xp(r.location,c);if(Ip&&!sd.get(i))if(f.isExternal||r.reloadDocument)window.location.href=f.absoluteURL||f.to;else{const g=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(f.to,{replace:r.replace}));throw sd.set(i,g),g}return j.createElement("meta",{httpEquiv:"refresh",content:`0;url=${f.absoluteURL||f.to}`})}}return a}function Oy({routeContext:a,match:i,children:c}){let r=j.useContext(xi);return r&&r.static&&r.staticContext&&(i.route.errorElement||i.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=i.route.id),j.createElement(Vn.Provider,{value:a},c)}function zy(a,i=[],c){let r=c==null?void 0:c.state;if(a==null){if(!r)return null;if(r.errors)a=r.matches;else if(i.length===0&&!r.initialized&&r.matches.length>0)a=r.matches;else return null}let d=a,f=r==null?void 0:r.errors;if(f!=null){let _=d.findIndex(y=>y.route.id&&(f==null?void 0:f[y.route.id])!==void 0);at(_>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(f).join(",")}`),d=d.slice(0,Math.min(d.length,_+1))}let g=!1,v=-1;if(c&&r){g=r.renderFallback;for(let _=0;_=0?d=d.slice(0,v+1):d=[d[0]];break}}}}let h=c==null?void 0:c.onError,m=r&&h?(_,y)=>{var b,N;h(_,{location:r.location,params:((N=(b=r.matches)==null?void 0:b[0])==null?void 0:N.params)??{},unstable_pattern:my(r.matches),errorInfo:y})}:void 0;return d.reduceRight((_,y,b)=>{let N,S=!1,E=null,T=null;r&&(N=f&&y.route.id?f[y.route.id]:void 0,E=y.route.errorElement||Ay,g&&(v<0&&b===0?(l3("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),S=!0,T=null):v===b&&(S=!0,T=y.route.hydrateFallbackElement||null)));let O=i.concat(d.slice(0,b+1)),H=()=>{let z;return N?z=E:S?z=T:y.route.Component?z=j.createElement(y.route.Component,null):y.route.element?z=y.route.element:z=_,j.createElement(Oy,{match:y,routeContext:{outlet:_,matches:O,isDataRoute:r!=null},children:z})};return r&&(y.route.ErrorBoundary||y.route.errorElement||b===0)?j.createElement(n3,{location:r.location,revalidation:r.revalidation,component:E,error:N,children:H(),routeContext:{outlet:null,matches:O,isDataRoute:!0},onError:m}):H()},null)}function Jd(a){return`${a} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function Dy(a){let i=j.useContext(xi);return at(i,Jd(a)),i}function Ly(a){let i=j.useContext(Ao);return at(i,Jd(a)),i}function ky(a){let i=j.useContext(Vn);return at(i,Jd(a)),i}function e2(a){let i=ky(a),c=i.matches[i.matches.length-1];return at(c.route.id,`${a} can only be used on routes that contain a unique "id"`),c.route.id}function By(){return e2("useRouteId")}function Uy(){var r;let a=j.useContext(Wd),i=Ly("useRouteError"),c=e2("useRouteError");return a!==void 0?a:(r=i.errors)==null?void 0:r[c]}function Hy(){let{router:a}=Dy("useNavigate"),i=e2("useNavigate"),c=j.useRef(!1);return e3(()=>{c.current=!0}),j.useCallback(async(d,f={})=>{Kn(c.current,Jp),c.current&&(typeof d=="number"?await a.navigate(d):await a.navigate(d,{fromRouteId:i,...f}))},[a,i])}var Am={};function l3(a,i,c){!i&&!Am[a]&&(Am[a]=!0,Kn(!1,c))}j.memo($y);function $y({routes:a,future:i,state:c,isStatic:r,onError:d}){return t3(a,void 0,{state:c,isStatic:r,onError:d})}function Mo({to:a,replace:i,state:c,relative:r}){at(bi()," may be used only in the context of a component.");let{static:d}=j.useContext(Cn);Kn(!d," must not be used on the initial render in a . This is a no-op, but you should modify your code so the is only ever rendered in response to some user interaction or state change.");let{matches:f}=j.useContext(Vn),{pathname:g}=En(),v=Tn(),h=Ro(a,Pd(f),g,r==="path"),m=JSON.stringify(h);return j.useEffect(()=>{v(JSON.parse(m),{replace:i,state:c,relative:r})},[v,m,r,i,c]),null}function t2(a){return Cy(a.context)}function We(a){at(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function qy({basename:a="/",children:i=null,location:c,navigationType:r="POP",navigator:d,static:f=!1,unstable_useTransitions:g}){at(!bi(),"You cannot render a inside another . You should never have more than one in your app.");let v=a.replace(/^\/*/,"/"),h=j.useMemo(()=>({basename:v,navigator:d,static:f,unstable_useTransitions:g,future:{}}),[v,d,f,g]);typeof c=="string"&&(c=yi(c));let{pathname:m="/",search:_="",hash:y="",state:b=null,key:N="default",unstable_mask:S}=c,E=j.useMemo(()=>{let T=Hl(m,v);return T==null?null:{location:{pathname:T,search:_,hash:y,state:b,key:N,unstable_mask:S},navigationType:r}},[v,m,_,y,b,N,r,S]);return Kn(E!=null,` is not able to match the URL "${m}${_}${y}" because it does not start with the basename, so the won't render anything.`),E==null?null:j.createElement(Cn.Provider,{value:h},j.createElement(Hc.Provider,{children:i,value:E}))}function Gy({children:a,location:i}){return Ty(Nd(a),i)}function Nd(a,i=[]){let c=[];return j.Children.forEach(a,(r,d)=>{if(!j.isValidElement(r))return;let f=[...i,d];if(r.type===j.Fragment){c.push.apply(c,Nd(r.props.children,f));return}at(r.type===We,`[${typeof r.type=="string"?r.type:r.type.name}] is not a component. All component children of must be a or `),at(!r.props.index||!r.props.children,"An index route cannot have child routes.");let g={id:r.props.id||f.join("-"),caseSensitive:r.props.caseSensitive,element:r.props.element,Component:r.props.Component,index:r.props.index,path:r.props.path,middleware:r.props.middleware,loader:r.props.loader,action:r.props.action,hydrateFallbackElement:r.props.hydrateFallbackElement,HydrateFallback:r.props.HydrateFallback,errorElement:r.props.errorElement,ErrorBoundary:r.props.ErrorBoundary,hasErrorBoundary:r.props.hasErrorBoundary===!0||r.props.ErrorBoundary!=null||r.props.errorElement!=null,shouldRevalidate:r.props.shouldRevalidate,handle:r.props.handle,lazy:r.props.lazy};r.props.children&&(g.children=Nd(r.props.children,f)),c.push(g)}),c}var go="get",_o="application/x-www-form-urlencoded";function Oo(a){return typeof HTMLElement<"u"&&a instanceof HTMLElement}function Fy(a){return Oo(a)&&a.tagName.toLowerCase()==="button"}function Vy(a){return Oo(a)&&a.tagName.toLowerCase()==="form"}function Qy(a){return Oo(a)&&a.tagName.toLowerCase()==="input"}function Yy(a){return!!(a.metaKey||a.altKey||a.ctrlKey||a.shiftKey)}function Iy(a,i){return a.button===0&&(!i||i==="_self")&&!Yy(a)}var ro=null;function Xy(){if(ro===null)try{new FormData(document.createElement("form"),0),ro=!1}catch{ro=!0}return ro}var Zy=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function id(a){return a!=null&&!Zy.has(a)?(Kn(!1,`"${a}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${_o}"`),null):a}function Ky(a,i){let c,r,d,f,g;if(Vy(a)){let v=a.getAttribute("action");r=v?Hl(v,i):null,c=a.getAttribute("method")||go,d=id(a.getAttribute("enctype"))||_o,f=new FormData(a)}else if(Fy(a)||Qy(a)&&(a.type==="submit"||a.type==="image")){let v=a.form;if(v==null)throw new Error('Cannot submit a - - - - -
АВТОМАТИЧЕСКОЕ СКРЫТИЕ ЧЕРЕЗ 14С
- -
1.egg
2.phone
3.long
4.vibe
5.potato
6.soup
7.skirt
8.black
9.phase
10.word
11.num
12.cucumber
- -
-
⚠️
-

Никогда не передавайте сид-фразу третьим лицам. Тот, кто знает фразу — владеет кошельком.

-
- - - - - - \ No newline at end of file diff --git a/src/app/providers/RouterProvider.tsx b/src/app/providers/RouterProvider.tsx index a02f25f..595cca1 100644 --- a/src/app/providers/RouterProvider.tsx +++ b/src/app/providers/RouterProvider.tsx @@ -18,6 +18,7 @@ import { PolitikaCookiePage } from '@pages/politika-cookie' import { SoglasiePage } from '@pages/soglasie-personalnyh-dannyh' import { ReestryPage } from '@pages/reestr-pd-rkn' import { TransactionsPage } from '@pages/transactions' +import { AdminPage } from '@pages/admin' import { WalletLayout } from '@widgets/wallet-layout' import { ROUTES } from '@shared/config/routes' import { ScrollToTop } from './ScrollToTop' @@ -38,6 +39,9 @@ export function RouterProvider() { } /> } /> + {/* Admin panel — own auth gate, independent of the user auth system */} + } /> + }> } /> } /> diff --git a/src/features/admin/api/adminApi.ts b/src/features/admin/api/adminApi.ts new file mode 100644 index 0000000..469ba9d --- /dev/null +++ b/src/features/admin/api/adminApi.ts @@ -0,0 +1,103 @@ +import type { + AdminLoginRequest, + AdminLoginResponse, + AdminMeResponse, + CreateOrganizationRequest, + Organization, + OrganizationListResponse, +} from '../model/types' + +const ADMIN_API_URL = 'https://app.admin.elcsa.ru/api' + +// In-memory admin access token — deliberately separate from the user `tokenStore` +// so the two independent auth systems never collide. No CSRF on the admin API. +let adminToken: string | null = null + +export const adminTokenStore = { + get: () => adminToken, + set: (token: string) => { adminToken = token }, + clear: () => { adminToken = null }, +} + +async function doAdminRequest( + path: string, + options: RequestInit, + allowRetry: boolean, +): Promise { + const bearer = adminTokenStore.get() + + const res = await fetch(`${ADMIN_API_URL}${path}`, { + ...options, + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + ...(bearer ? { Authorization: `Bearer ${bearer}` } : {}), + ...options.headers, + }, + }) + + if (res.status === 401 && allowRetry) { + try { + await refreshAdminToken() + return doAdminRequest(path, options, false) + } catch { + adminTokenStore.clear() + throw new Error('Unauthorized') + } + } + + const data = await res.json().catch(() => null) + if (!res.ok) throw data + return data as T +} + +// Refresh by analogy with the main auth service: HttpOnly refresh cookie -> fresh access token. +// Exact path is isolated here — adjust if the backend differs (e.g. /v1/jwt/refresh). +export async function refreshAdminToken(): Promise { + const res = await fetch(`${ADMIN_API_URL}/v1/auth/refresh`, { + method: 'POST', + credentials: 'include', + }) + if (!res.ok) throw new Error('Unauthorized') + const data = await res.json() + if (data.access_token) adminTokenStore.set(data.access_token) + return (data.access_token ?? true) as string +} + +export async function adminLogin(payload: AdminLoginRequest): Promise { + const data = await doAdminRequest( + '/v1/auth/login', + { method: 'POST', body: JSON.stringify(payload) }, + false, + ) + if (data.access_token) adminTokenStore.set(data.access_token) + return data +} + +export function getAdminMe(): Promise { + return doAdminRequest('/v1/auth/me', {}, true) +} + +export async function adminLogout(): Promise { + try { + await doAdminRequest('/v1/auth/logout', { method: 'POST' }, false) + } finally { + adminTokenStore.clear() + } +} + +export function getOrganizations(limit = 50, offset = 0): Promise { + return doAdminRequest( + `/v1/organizations?limit=${limit}&offset=${offset}`, + {}, + true, + ) +} + +export function createOrganization(payload: CreateOrganizationRequest): Promise { + return doAdminRequest( + '/v1/organizations', + { method: 'POST', body: JSON.stringify(payload) }, + true, + ) +} diff --git a/src/features/admin/hooks/useAdminAuth.ts b/src/features/admin/hooks/useAdminAuth.ts new file mode 100644 index 0000000..2b2f7d0 --- /dev/null +++ b/src/features/admin/hooks/useAdminAuth.ts @@ -0,0 +1,16 @@ +import { useQuery } from '@tanstack/react-query' +import { refreshAdminToken } from '../api/adminApi' + +export const ADMIN_AUTH_QUERY_KEY = ['admin-auth'] + +export function useAdminAuth(): { isAuthenticated: boolean; isLoading: boolean } { + const { data, isLoading, isError } = useQuery({ + queryKey: ADMIN_AUTH_QUERY_KEY, + queryFn: refreshAdminToken, + retry: false, + staleTime: Infinity, + gcTime: Infinity, + refetchOnWindowFocus: false, + }) + return { isAuthenticated: !!data && !isError, isLoading } +} diff --git a/src/features/admin/hooks/useAdminLogin.ts b/src/features/admin/hooks/useAdminLogin.ts new file mode 100644 index 0000000..26c647a --- /dev/null +++ b/src/features/admin/hooks/useAdminLogin.ts @@ -0,0 +1,13 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query' +import { adminLogin } from '../api/adminApi' +import { ADMIN_AUTH_QUERY_KEY } from './useAdminAuth' + +export function useAdminLogin() { + const queryClient = useQueryClient() + return useMutation({ + mutationFn: adminLogin, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ADMIN_AUTH_QUERY_KEY }) + }, + }) +} diff --git a/src/features/admin/hooks/useAdminLogout.ts b/src/features/admin/hooks/useAdminLogout.ts new file mode 100644 index 0000000..22803dd --- /dev/null +++ b/src/features/admin/hooks/useAdminLogout.ts @@ -0,0 +1,13 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query' +import { adminLogout } from '../api/adminApi' +import { ADMIN_AUTH_QUERY_KEY } from './useAdminAuth' + +export function useAdminLogout() { + const queryClient = useQueryClient() + return useMutation({ + mutationFn: adminLogout, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ADMIN_AUTH_QUERY_KEY }) + }, + }) +} diff --git a/src/features/admin/hooks/useCreateOrganization.ts b/src/features/admin/hooks/useCreateOrganization.ts new file mode 100644 index 0000000..b35dedb --- /dev/null +++ b/src/features/admin/hooks/useCreateOrganization.ts @@ -0,0 +1,13 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query' +import { createOrganization } from '../api/adminApi' +import { ORGANIZATIONS_QUERY_KEY } from './useOrganizations' + +export function useCreateOrganization() { + const queryClient = useQueryClient() + return useMutation({ + mutationFn: createOrganization, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ORGANIZATIONS_QUERY_KEY }) + }, + }) +} diff --git a/src/features/admin/hooks/useOrganizations.ts b/src/features/admin/hooks/useOrganizations.ts new file mode 100644 index 0000000..f8584c6 --- /dev/null +++ b/src/features/admin/hooks/useOrganizations.ts @@ -0,0 +1,11 @@ +import { useQuery } from '@tanstack/react-query' +import { getOrganizations } from '../api/adminApi' + +export const ORGANIZATIONS_QUERY_KEY = ['admin-organizations'] + +export function useOrganizations() { + return useQuery({ + queryKey: ORGANIZATIONS_QUERY_KEY, + queryFn: () => getOrganizations(), + }) +} diff --git a/src/features/admin/index.ts b/src/features/admin/index.ts new file mode 100644 index 0000000..3090b46 --- /dev/null +++ b/src/features/admin/index.ts @@ -0,0 +1,23 @@ +export { + adminLogin, + adminLogout, + getAdminMe, + getOrganizations, + createOrganization, + refreshAdminToken, + adminTokenStore, +} from './api/adminApi' +export type { + AdminLoginRequest, + AdminLoginResponse, + AdminMeResponse, + Organization, + OrganizationListResponse, + CreateOrganizationRequest, + BankDetails, +} from './model/types' +export { useAdminAuth, ADMIN_AUTH_QUERY_KEY } from './hooks/useAdminAuth' +export { useAdminLogin } from './hooks/useAdminLogin' +export { useAdminLogout } from './hooks/useAdminLogout' +export { useOrganizations, ORGANIZATIONS_QUERY_KEY } from './hooks/useOrganizations' +export { useCreateOrganization } from './hooks/useCreateOrganization' diff --git a/src/features/admin/model/types.ts b/src/features/admin/model/types.ts new file mode 100644 index 0000000..c316f03 --- /dev/null +++ b/src/features/admin/model/types.ts @@ -0,0 +1,67 @@ +export interface AdminLoginRequest { + login: string + password: string +} + +export interface AdminLoginResponse { + access_token: string + token_type: string + id: string + login: string + first_name: string | null + last_name: string | null + role: string +} + +export interface AdminMeResponse { + id: string + login: string + first_name: string | null + last_name: string | null + role: string +} + +export type BankDetails = Record + +export interface Organization { + id: string + user_id: string + name: string + short_name: string | null + inn: string + ogrn: string | null + kpp: string | null + legal_address: string | null + actual_address: string | null + bank_details: BankDetails | null + contact_person: string | null + contact_phone: string | null + status: string + kyc_verified: boolean + kyc_verified_at: string | null + has_wallets: boolean + created_by: string | null + created_at: string | null + updated_at: string | null +} + +export interface OrganizationListResponse { + items: Organization[] + total: number +} + +export interface CreateOrganizationRequest { + email: string + password: string + name: string + inn: string + short_name?: string | null + ogrn?: string | null + kpp?: string | null + legal_address?: string | null + actual_address?: string | null + bank_details?: BankDetails | null + contact_person?: string | null + contact_phone?: string | null + status?: string +} diff --git a/src/openapi.json b/src/openapi.json new file mode 100644 index 0000000..dee1dd5 --- /dev/null +++ b/src/openapi.json @@ -0,0 +1,3106 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Bitforce. Admin Service", + "description": "Admin API for legal entities, wallets, documents, and B2B purchase requests", + "license": { + "name": "MIT", + "url": "https://opensource.org/licenses/MIT" + }, + "version": "1.0.0" + }, + "paths": { + "/v1/auth/login": { + "post": { + "tags": [ + "auth" + ], + "summary": "Admin Login", + "operationId": "admin_login_v1_auth_login_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AdminLoginRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AdminLoginResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/auth/logout": { + "post": { + "tags": [ + "auth" + ], + "summary": "Admin Logout", + "description": "Клиент удаляет access_token локально. Сервер stateless.", + "operationId": "admin_logout_v1_auth_logout_post", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/auth/me": { + "get": { + "tags": [ + "auth" + ], + "summary": "Admin Me", + "operationId": "admin_me_v1_auth_me_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AdminMeResponse" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/organizations": { + "get": { + "tags": [ + "organizations" + ], + "summary": "List Organizations", + "operationId": "list_organizations_v1_organizations_get", + "parameters": [ + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 200, + "minimum": 1, + "default": 50, + "title": "Limit" + } + }, + { + "name": "offset", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "default": 0, + "title": "Offset" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "post": { + "tags": [ + "organizations" + ], + "summary": "Create Organization", + "operationId": "create_organization_v1_organizations_post", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateOrganizationRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/organizations/{organization_id}": { + "get": { + "tags": [ + "organizations" + ], + "summary": "Get Organization", + "operationId": "get_organization_v1_organizations__organization_id__get", + "parameters": [ + { + "name": "organization_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Organization Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "patch": { + "tags": [ + "organizations" + ], + "summary": "Update Organization", + "operationId": "update_organization_v1_organizations__organization_id__patch", + "parameters": [ + { + "name": "organization_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Organization Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateOrganizationRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrganizationResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/organizations/{organization_id}/wallets/create": { + "post": { + "tags": [ + "organizations" + ], + "summary": "Create Organization Wallets", + "operationId": "create_organization_wallets_v1_organizations__organization_id__wallets_create_post", + "parameters": [ + { + "name": "organization_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Organization Id" + } + } + ], + "responses": { + "201": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WalletResponse" + }, + "title": "Response Create Organization Wallets V1 Organizations Organization Id Wallets Create Post" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/organizations/{organization_id}/documents": { + "get": { + "tags": [ + "documents" + ], + "summary": "List Documents", + "operationId": "list_documents_v1_organizations__organization_id__documents_get", + "parameters": [ + { + "name": "organization_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Organization Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DocumentResponse" + }, + "title": "Response List Documents V1 Organizations Organization Id Documents Get" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "post": { + "tags": [ + "documents" + ], + "summary": "Upload Document", + "operationId": "upload_document_v1_organizations__organization_id__documents_post", + "parameters": [ + { + "name": "organization_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Organization Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/Body_upload_document_v1_organizations__organization_id__documents_post" + } + } + } + }, + "responses": { + "201": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/organizations/{organization_id}/documents/{document_id}": { + "get": { + "tags": [ + "documents" + ], + "summary": "Get Document", + "operationId": "get_document_v1_organizations__organization_id__documents__document_id__get", + "parameters": [ + { + "name": "organization_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Organization Id" + } + }, + { + "name": "document_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Document Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DocumentResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/purchase-requests": { + "get": { + "tags": [ + "purchase-requests" + ], + "summary": "List Purchase Requests", + "operationId": "list_purchase_requests_v1_purchase_requests_get", + "parameters": [ + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "name": "organization_id", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Organization Id" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 200, + "minimum": 1, + "default": 50, + "title": "Limit" + } + }, + { + "name": "offset", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "default": 0, + "title": "Offset" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PurchaseRequestListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/purchase-requests/{request_id}": { + "get": { + "tags": [ + "purchase-requests" + ], + "summary": "Get Purchase Request", + "operationId": "get_purchase_request_v1_purchase_requests__request_id__get", + "parameters": [ + { + "name": "request_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Request Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PurchaseRequestResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/purchase-requests/{request_id}/status": { + "patch": { + "tags": [ + "purchase-requests" + ], + "summary": "Update Purchase Request Status", + "operationId": "update_purchase_request_status_v1_purchase_requests__request_id__status_patch", + "parameters": [ + { + "name": "request_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Request Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdatePurchaseRequestStatusBody" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PurchaseRequestResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/v1/purchase-requests/{request_id}/quote": { + "post": { + "tags": [ + "purchase-requests" + ], + "summary": "Set Purchase Request Quote", + "operationId": "set_purchase_request_quote_v1_purchase_requests__request_id__quote_post", + "parameters": [ + { + "name": "request_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Request Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetPurchaseRequestQuoteBody" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PurchaseRequestResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/ping": { + "post": { + "summary": "Ping", + "operationId": "ping_ping_post", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "title": "Response Ping Ping Post" + } + } + } + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "409": { + "description": "Conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "429": { + "description": "Too Many Requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "503": { + "description": "Service Unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "AdminLoginRequest": { + "properties": { + "login": { + "type": "string", + "maxLength": 255, + "minLength": 3, + "title": "Login" + }, + "password": { + "type": "string", + "minLength": 8, + "title": "Password" + } + }, + "type": "object", + "required": [ + "login", + "password" + ], + "title": "AdminLoginRequest" + }, + "AdminLoginResponse": { + "properties": { + "access_token": { + "type": "string", + "title": "Access Token" + }, + "token_type": { + "type": "string", + "title": "Token Type", + "default": "Bearer" + }, + "id": { + "type": "string", + "title": "Id" + }, + "login": { + "type": "string", + "title": "Login" + }, + "first_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "First Name" + }, + "last_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Name" + }, + "role": { + "type": "string", + "title": "Role" + } + }, + "type": "object", + "required": [ + "access_token", + "id", + "login", + "first_name", + "last_name", + "role" + ], + "title": "AdminLoginResponse" + }, + "AdminMeResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id" + }, + "login": { + "type": "string", + "title": "Login" + }, + "first_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "First Name" + }, + "last_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Name" + }, + "role": { + "type": "string", + "title": "Role" + } + }, + "type": "object", + "required": [ + "id", + "login", + "first_name", + "last_name", + "role" + ], + "title": "AdminMeResponse" + }, + "Body_upload_document_v1_organizations__organization_id__documents_post": { + "properties": { + "document_type": { + "type": "string", + "title": "Document Type" + }, + "file": { + "type": "string", + "format": "binary", + "title": "File" + } + }, + "type": "object", + "required": [ + "document_type", + "file" + ], + "title": "Body_upload_document_v1_organizations__organization_id__documents_post" + }, + "CreateOrganizationRequest": { + "properties": { + "email": { + "type": "string", + "maxLength": 255, + "minLength": 3, + "title": "Email" + }, + "password": { + "type": "string", + "minLength": 8, + "title": "Password" + }, + "name": { + "type": "string", + "maxLength": 512, + "minLength": 1, + "title": "Name" + }, + "short_name": { + "anyOf": [ + { + "type": "string", + "maxLength": 256 + }, + { + "type": "null" + } + ], + "title": "Short Name" + }, + "inn": { + "type": "string", + "maxLength": 12, + "minLength": 10, + "title": "Inn" + }, + "ogrn": { + "anyOf": [ + { + "type": "string", + "maxLength": 15 + }, + { + "type": "null" + } + ], + "title": "Ogrn" + }, + "kpp": { + "anyOf": [ + { + "type": "string", + "maxLength": 9 + }, + { + "type": "null" + } + ], + "title": "Kpp" + }, + "legal_address": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Address" + }, + "actual_address": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Actual Address" + }, + "bank_details": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Bank Details" + }, + "contact_person": { + "anyOf": [ + { + "type": "string", + "maxLength": 256 + }, + { + "type": "null" + } + ], + "title": "Contact Person" + }, + "contact_phone": { + "anyOf": [ + { + "type": "string", + "maxLength": 16 + }, + { + "type": "null" + } + ], + "title": "Contact Phone" + }, + "status": { + "type": "string", + "title": "Status", + "default": "active" + } + }, + "type": "object", + "required": [ + "email", + "password", + "name", + "inn" + ], + "title": "CreateOrganizationRequest" + }, + "DocumentResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id" + }, + "organization_id": { + "type": "string", + "title": "Organization Id" + }, + "document_type": { + "type": "string", + "title": "Document Type" + }, + "file_name": { + "type": "string", + "title": "File Name" + }, + "content_type": { + "type": "string", + "title": "Content Type" + }, + "file_size_bytes": { + "type": "integer", + "title": "File Size Bytes" + }, + "uploaded_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Uploaded By" + }, + "created_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Created At" + }, + "download_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Download Url" + } + }, + "type": "object", + "required": [ + "id", + "organization_id", + "document_type", + "file_name", + "content_type", + "file_size_bytes", + "uploaded_by", + "created_at" + ], + "title": "DocumentResponse" + }, + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail" + } + }, + "type": "object", + "title": "HTTPValidationError" + }, + "OrganizationListResponse": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/OrganizationResponse" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "title": "Total" + } + }, + "type": "object", + "required": [ + "items", + "total" + ], + "title": "OrganizationListResponse" + }, + "OrganizationResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id" + }, + "user_id": { + "type": "string", + "title": "User Id" + }, + "name": { + "type": "string", + "title": "Name" + }, + "short_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Short Name" + }, + "inn": { + "type": "string", + "title": "Inn" + }, + "ogrn": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Ogrn" + }, + "kpp": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Kpp" + }, + "legal_address": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Address" + }, + "actual_address": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Actual Address" + }, + "bank_details": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Bank Details" + }, + "contact_person": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Contact Person" + }, + "contact_phone": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Contact Phone" + }, + "status": { + "type": "string", + "title": "Status" + }, + "kyc_verified": { + "type": "boolean", + "title": "Kyc Verified" + }, + "kyc_verified_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Kyc Verified At" + }, + "has_wallets": { + "type": "boolean", + "title": "Has Wallets" + }, + "created_by": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Created By" + }, + "created_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Created At" + }, + "updated_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Updated At" + } + }, + "type": "object", + "required": [ + "id", + "user_id", + "name", + "short_name", + "inn", + "ogrn", + "kpp", + "legal_address", + "actual_address", + "bank_details", + "contact_person", + "contact_phone", + "status", + "kyc_verified", + "kyc_verified_at", + "has_wallets", + "created_by", + "created_at", + "updated_at" + ], + "title": "OrganizationResponse" + }, + "PurchaseRequestListResponse": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/PurchaseRequestResponse" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "title": "Total" + } + }, + "type": "object", + "required": [ + "items", + "total" + ], + "title": "PurchaseRequestListResponse" + }, + "PurchaseRequestResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id" + }, + "organization_id": { + "type": "string", + "title": "Organization Id" + }, + "status": { + "type": "string", + "title": "Status" + }, + "usdt_amount": { + "type": "string", + "title": "Usdt Amount" + }, + "rub_amount": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Rub Amount" + }, + "exchange_rate": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Exchange Rate" + }, + "service_fee_percent": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Service Fee Percent" + }, + "comment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Comment" + }, + "admin_comment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Admin Comment" + }, + "target_wallet_chain": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Target Wallet Chain" + }, + "target_wallet_address": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Target Wallet Address" + }, + "tx_hash": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tx Hash" + }, + "assigned_to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Assigned To" + }, + "created_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Created At" + }, + "updated_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Updated At" + }, + "completed_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Completed At" + } + }, + "type": "object", + "required": [ + "id", + "organization_id", + "status", + "usdt_amount", + "rub_amount", + "exchange_rate", + "service_fee_percent", + "comment", + "admin_comment", + "target_wallet_chain", + "target_wallet_address", + "tx_hash", + "assigned_to", + "created_at", + "updated_at", + "completed_at" + ], + "title": "PurchaseRequestResponse" + }, + "SetPurchaseRequestQuoteBody": { + "properties": { + "rub_amount": { + "anyOf": [ + { + "type": "number", + "exclusiveMinimum": 0.0 + }, + { + "type": "string", + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$" + } + ], + "title": "Rub Amount" + }, + "exchange_rate": { + "anyOf": [ + { + "type": "number", + "exclusiveMinimum": 0.0 + }, + { + "type": "string", + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$" + } + ], + "title": "Exchange Rate" + }, + "service_fee_percent": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string", + "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$" + }, + { + "type": "null" + } + ], + "title": "Service Fee Percent" + }, + "admin_comment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Admin Comment" + } + }, + "type": "object", + "required": [ + "rub_amount", + "exchange_rate" + ], + "title": "SetPurchaseRequestQuoteBody" + }, + "UpdateOrganizationRequest": { + "properties": { + "name": { + "anyOf": [ + { + "type": "string", + "maxLength": 512 + }, + { + "type": "null" + } + ], + "title": "Name" + }, + "short_name": { + "anyOf": [ + { + "type": "string", + "maxLength": 256 + }, + { + "type": "null" + } + ], + "title": "Short Name" + }, + "ogrn": { + "anyOf": [ + { + "type": "string", + "maxLength": 15 + }, + { + "type": "null" + } + ], + "title": "Ogrn" + }, + "kpp": { + "anyOf": [ + { + "type": "string", + "maxLength": 9 + }, + { + "type": "null" + } + ], + "title": "Kpp" + }, + "legal_address": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Legal Address" + }, + "actual_address": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Actual Address" + }, + "bank_details": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Bank Details" + }, + "contact_person": { + "anyOf": [ + { + "type": "string", + "maxLength": 256 + }, + { + "type": "null" + } + ], + "title": "Contact Person" + }, + "contact_phone": { + "anyOf": [ + { + "type": "string", + "maxLength": 16 + }, + { + "type": "null" + } + ], + "title": "Contact Phone" + }, + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + "type": "object", + "title": "UpdateOrganizationRequest" + }, + "UpdatePurchaseRequestStatusBody": { + "properties": { + "status": { + "type": "string", + "title": "Status" + }, + "admin_comment": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Admin Comment" + }, + "assigned_to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Assigned To" + }, + "tx_hash": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Tx Hash" + } + }, + "type": "object", + "required": [ + "status" + ], + "title": "UpdatePurchaseRequestStatusBody" + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "type": "array", + "title": "Location" + }, + "msg": { + "type": "string", + "title": "Message" + }, + "type": { + "type": "string", + "title": "Error Type" + }, + "input": { + "title": "Input" + }, + "ctx": { + "type": "object", + "title": "Context" + } + }, + "type": "object", + "required": [ + "loc", + "msg", + "type" + ], + "title": "ValidationError" + }, + "WalletResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id" + }, + "chain": { + "type": "string", + "title": "Chain" + }, + "address": { + "type": "string", + "title": "Address" + }, + "derivation_path": { + "type": "string", + "title": "Derivation Path" + }, + "created_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Created At" + } + }, + "type": "object", + "required": [ + "id", + "chain", + "address", + "derivation_path", + "created_at" + ], + "title": "WalletResponse" + }, + "ErrorResponse": { + "properties": { + "detail": { + "title": "Detail", + "type": "string" + } + }, + "required": [ + "detail" + ], + "title": "ErrorResponse", + "type": "object" + } + } + } +} \ No newline at end of file diff --git a/src/pages/admin/index.ts b/src/pages/admin/index.ts new file mode 100644 index 0000000..7f56083 --- /dev/null +++ b/src/pages/admin/index.ts @@ -0,0 +1 @@ +export { AdminPage } from './ui/AdminPage' diff --git a/src/pages/admin/ui/AdminPage.module.css b/src/pages/admin/ui/AdminPage.module.css new file mode 100644 index 0000000..bcf01c8 --- /dev/null +++ b/src/pages/admin/ui/AdminPage.module.css @@ -0,0 +1,84 @@ +.page { + min-height: 100vh; + background: var(--bg-deep); + padding: 40px 48px; +} + +.header { + display: flex; + align-items: center; + justify-content: space-between; + max-width: 1200px; + margin: 0 auto 36px; +} + +.greeting { + font-size: clamp(28px, 4vw, 40px); + font-weight: 700; + color: var(--text-primary, #fff); + margin: 0; +} + +.logout { + background: rgba(255, 255, 255, 0.06); + border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1)); + color: var(--text-secondary, rgba(255, 255, 255, 0.7)); + border-radius: 10px; + height: 40px; + padding: 0 18px; + font-size: 13px; + font-weight: 600; + cursor: pointer; + transition: background 0.2s, color 0.2s, border-color 0.2s; +} + +.logout:hover { + background: rgba(255, 90, 90, 0.12); + border-color: rgba(255, 90, 90, 0.3); + color: #ff5a5a; +} + +.content { + max-width: 1200px; + margin: 0 auto; +} + +.toolbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + margin-bottom: 20px; + flex-wrap: wrap; +} + +.sectionTitle { + font-size: 20px; + font-weight: 700; + color: var(--text-primary, #fff); + margin: 0; +} + +.addBtn { + background: linear-gradient(135deg, var(--grad-edge, #4a6dff), var(--grad-center, #6f4aff)); + border: none; + color: #fff; + border-radius: 12px; + height: 44px; + padding: 0 20px; + font-size: 14px; + font-weight: 700; + cursor: pointer; + transition: filter 0.2s, box-shadow 0.2s; +} + +.addBtn:hover { + filter: brightness(1.12); + box-shadow: 0 6px 20px rgba(74, 109, 255, 0.35); +} + +@media (max-width: 768px) { + .page { + padding: 28px 20px; + } +} diff --git a/src/pages/admin/ui/AdminPage.tsx b/src/pages/admin/ui/AdminPage.tsx new file mode 100644 index 0000000..dd9c2d0 --- /dev/null +++ b/src/pages/admin/ui/AdminPage.tsx @@ -0,0 +1,53 @@ +import { useState } from 'react' +import { useAdminAuth, useAdminLogout } from '@features/admin' +import { Notification } from '@shared/ui' +import { AdminLoginForm } from '@widgets/admin-login-form' +import { LegalEntitiesTable } from '@widgets/legal-entities-table' +import { AddLegalEntityModal } from '@widgets/add-legal-entity-modal' +import styles from './AdminPage.module.css' + +export function AdminPage() { + const { isAuthenticated, isLoading } = useAdminAuth() + const logout = useAdminLogout() + const [modalOpen, setModalOpen] = useState(false) + const [notification, setNotification] = useState<{ message: string; status: 'success' | 'error' } | null>(null) + + if (isLoading) return null + if (!isAuthenticated) return + + return ( +
+
+

Привет, Марк!

+ +
+ +
+
+

Юридические лица

+ +
+ + +
+ + setModalOpen(false)} + onCreated={() => setNotification({ status: 'success', message: 'Юридическое лицо добавлено' })} + /> + + {notification && ( + setNotification(null)} + /> + )} +
+ ) +} diff --git a/src/shared/config/routes.ts b/src/shared/config/routes.ts index 5a51a86..e58990e 100644 --- a/src/shared/config/routes.ts +++ b/src/shared/config/routes.ts @@ -19,4 +19,5 @@ export const ROUTES = { SOGLASIE_PERSONALNYH_DANNYH: '/soglasie-personalnyh-dannyh', REESTR_PD_RKN: '/reestr-pd-rkn', TRANSACTIONS: '/transactions', + ADMIN: '/sys-c7f29a4e-d81b-4630-ops-console', } as const diff --git a/src/widgets/add-legal-entity-modal/index.ts b/src/widgets/add-legal-entity-modal/index.ts new file mode 100644 index 0000000..0f639e1 --- /dev/null +++ b/src/widgets/add-legal-entity-modal/index.ts @@ -0,0 +1 @@ +export { AddLegalEntityModal } from './ui/AddLegalEntityModal' diff --git a/src/widgets/add-legal-entity-modal/model/useAddLegalEntityForm.ts b/src/widgets/add-legal-entity-modal/model/useAddLegalEntityForm.ts new file mode 100644 index 0000000..c3858a1 --- /dev/null +++ b/src/widgets/add-legal-entity-modal/model/useAddLegalEntityForm.ts @@ -0,0 +1,86 @@ +import { useState } from 'react' +import { useCreateOrganization } from '@features/admin' +import type { CreateOrganizationRequest } from '@features/admin' + +const INITIAL = { + email: '', + password: '', + name: '', + inn: '', + short_name: '', + ogrn: '', + kpp: '', + legal_address: '', + actual_address: '', + contact_person: '', + contact_phone: '', + status: 'active', + bank_name: '', + bik: '', + account: '', + corr_account: '', +} + +type FormState = typeof INITIAL + +function extractErrorMessage(error: unknown): string { + const e = error as { detail?: unknown } + if (typeof e?.detail === 'string') return e.detail + if (Array.isArray(e?.detail) && (e.detail[0] as { msg?: string })?.msg) { + return (e.detail[0] as { msg: string }).msg + } + return 'Не удалось добавить юридическое лицо' +} + +export function useAddLegalEntityForm(onSuccess: () => void) { + const [form, setForm] = useState(INITIAL) + const mutation = useCreateOrganization() + + const setField = (key: keyof FormState) => (value: string) => + setForm((prev) => ({ ...prev, [key]: value })) + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault() + + const trimmedOrNull = (v: string) => (v.trim() ? v.trim() : null) + + const bankEntries: Record = {} + if (form.bank_name.trim()) bankEntries.bank_name = form.bank_name.trim() + if (form.bik.trim()) bankEntries.bik = form.bik.trim() + if (form.account.trim()) bankEntries.account = form.account.trim() + if (form.corr_account.trim()) bankEntries.corr_account = form.corr_account.trim() + + const payload: CreateOrganizationRequest = { + email: form.email.trim(), + password: form.password, + name: form.name.trim(), + inn: form.inn.trim(), + short_name: trimmedOrNull(form.short_name), + ogrn: trimmedOrNull(form.ogrn), + kpp: trimmedOrNull(form.kpp), + legal_address: trimmedOrNull(form.legal_address), + actual_address: trimmedOrNull(form.actual_address), + contact_person: trimmedOrNull(form.contact_person), + contact_phone: trimmedOrNull(form.contact_phone), + bank_details: Object.keys(bankEntries).length ? bankEntries : null, + status: form.status.trim() || 'active', + } + + mutation.mutate(payload, { + onSuccess: () => { + setForm(INITIAL) + onSuccess() + }, + }) + } + + const error = mutation.isError ? extractErrorMessage(mutation.error) : null + + return { + form, + setField, + handleSubmit, + isLoading: mutation.isPending, + error, + } +} diff --git a/src/widgets/add-legal-entity-modal/ui/AddLegalEntityModal.module.css b/src/widgets/add-legal-entity-modal/ui/AddLegalEntityModal.module.css new file mode 100644 index 0000000..62d29e1 --- /dev/null +++ b/src/widgets/add-legal-entity-modal/ui/AddLegalEntityModal.module.css @@ -0,0 +1,101 @@ +@keyframes dialogIn { + from { opacity: 0; transform: scale(0.96); } + to { opacity: 1; transform: scale(1); } +} + +.overlay { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.6); + backdrop-filter: blur(4px); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + padding: 16px; +} + +.dialog { + background: var(--bg-mid, #151520); + border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1)); + border-radius: 20px; + width: 100%; + max-width: 720px; + max-height: 90vh; + display: flex; + flex-direction: column; + animation: dialogIn 0.18s ease; +} + +.header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 20px 24px 0; + flex-shrink: 0; +} + +.title { + font-size: 17px; + font-weight: 700; + color: var(--text-primary, #fff); +} + +.closeBtn { + background: none; + border: none; + color: var(--text-secondary, rgba(255, 255, 255, 0.4)); + font-size: 16px; + cursor: pointer; + padding: 4px; + line-height: 1; + transition: color 0.15s; +} + +.closeBtn:hover { + color: var(--text-primary, #fff); +} + +.body { + padding: 16px 24px 24px; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 8px; +} + +.groupLabel { + font-size: 12px; + letter-spacing: 1.5px; + text-transform: uppercase; + color: var(--text-secondary, rgba(255, 255, 255, 0.5)); + font-weight: 600; + margin: 16px 0 4px; +} + +.groupLabel:first-child { + margin-top: 4px; +} + +.grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; +} + +.error { + color: #ff5a5a; + font-size: 13px; + margin: 12px 0 0; + text-align: center; +} + +.actions { + margin-top: 20px; +} + +@media (max-width: 560px) { + .grid { + grid-template-columns: 1fr; + } +} diff --git a/src/widgets/add-legal-entity-modal/ui/AddLegalEntityModal.tsx b/src/widgets/add-legal-entity-modal/ui/AddLegalEntityModal.tsx new file mode 100644 index 0000000..91243ba --- /dev/null +++ b/src/widgets/add-legal-entity-modal/ui/AddLegalEntityModal.tsx @@ -0,0 +1,79 @@ +import { useEffect } from 'react' +import { FormField, PrimaryButton } from '@shared/ui' +import { useAddLegalEntityForm } from '../model/useAddLegalEntityForm' +import styles from './AddLegalEntityModal.module.css' + +interface Props { + open: boolean + onClose: () => void + onCreated: () => void +} + +export function AddLegalEntityModal({ open, onClose, onCreated }: Props) { + const { form, setField, handleSubmit, isLoading, error } = useAddLegalEntityForm(() => { + onCreated() + onClose() + }) + + useEffect(() => { + if (!open) return + function onKey(e: KeyboardEvent) { + if (e.key === 'Escape') onClose() + } + window.addEventListener('keydown', onKey) + return () => window.removeEventListener('keydown', onKey) + }, [open, onClose]) + + if (!open) return null + + function handleOverlay(e: React.MouseEvent) { + if (e.target === e.currentTarget) onClose() + } + + return ( +
+
+
+ Добавить юридическое лицо + +
+ + +

Обязательные поля

+
+ + + + +
+ +

Дополнительные поля

+
+ + + + + + + + +
+ +

Банковские реквизиты

+
+ + + + +
+ + {error &&

{error}

} + +
+ +
+ +
+
+ ) +} diff --git a/src/widgets/admin-login-form/index.ts b/src/widgets/admin-login-form/index.ts new file mode 100644 index 0000000..b417604 --- /dev/null +++ b/src/widgets/admin-login-form/index.ts @@ -0,0 +1 @@ +export { AdminLoginForm } from './ui/AdminLoginForm' diff --git a/src/widgets/admin-login-form/model/useAdminLoginForm.ts b/src/widgets/admin-login-form/model/useAdminLoginForm.ts new file mode 100644 index 0000000..6f430ab --- /dev/null +++ b/src/widgets/admin-login-form/model/useAdminLoginForm.ts @@ -0,0 +1,35 @@ +import { useState } from 'react' +import { useAdminLogin } from '@features/admin' + +function extractErrorMessage(error: unknown): string { + const e = error as { detail?: unknown } + if (typeof e?.detail === 'string') return e.detail + if (Array.isArray(e?.detail) && (e.detail[0] as { msg?: string })?.msg) { + return (e.detail[0] as { msg: string }).msg + } + return 'Неверный логин или пароль' +} + +export function useAdminLoginForm() { + const [login, setLogin] = useState('') + const [password, setPassword] = useState('') + const loginMutation = useAdminLogin() + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault() + if (!login || !password) return + loginMutation.mutate({ login, password }) + } + + const error = loginMutation.isError ? extractErrorMessage(loginMutation.error) : null + + return { + login, + setLogin, + password, + setPassword, + isLoading: loginMutation.isPending, + error, + handleSubmit, + } +} diff --git a/src/widgets/admin-login-form/ui/AdminLoginForm.module.css b/src/widgets/admin-login-form/ui/AdminLoginForm.module.css new file mode 100644 index 0000000..4d9c196 --- /dev/null +++ b/src/widgets/admin-login-form/ui/AdminLoginForm.module.css @@ -0,0 +1,49 @@ +.wrap { + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: 24px; + background: var(--bg-deep); +} + +.card { + background: var(--glass-bg, rgba(255, 255, 255, 0.06)); + border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1)); + border-radius: 24px; + padding: 36px 32px; + width: 100%; + max-width: 420px; +} + +.title { + text-align: center; + font-size: 24px; + font-weight: 700; + color: var(--text-primary, #fff); + margin: 0 0 4px; +} + +.subtitle { + text-align: center; + font-size: 14px; + color: var(--text-secondary, rgba(255, 255, 255, 0.5)); + margin: 0 0 28px; +} + +.fields { + display: flex; + flex-direction: column; + gap: 18px; +} + +.error { + color: #ff5a5a; + font-size: 13px; + margin: 14px 0 0; + text-align: center; +} + +.submit { + margin-top: 26px; +} diff --git a/src/widgets/admin-login-form/ui/AdminLoginForm.tsx b/src/widgets/admin-login-form/ui/AdminLoginForm.tsx new file mode 100644 index 0000000..948342e --- /dev/null +++ b/src/widgets/admin-login-form/ui/AdminLoginForm.tsx @@ -0,0 +1,40 @@ +import { FormField, PrimaryButton } from '@shared/ui' +import { useAdminLoginForm } from '../model/useAdminLoginForm' +import styles from './AdminLoginForm.module.css' + +export function AdminLoginForm() { + const { login, setLogin, password, setPassword, isLoading, error, handleSubmit } = useAdminLoginForm() + + return ( +
+
+

Панель администратора

+

Войдите, чтобы продолжить

+ +
+ + +
+ + {error &&

{error}

} + +
+ +
+
+
+ ) +} diff --git a/src/widgets/legal-entities-table/index.ts b/src/widgets/legal-entities-table/index.ts new file mode 100644 index 0000000..828de42 --- /dev/null +++ b/src/widgets/legal-entities-table/index.ts @@ -0,0 +1 @@ +export { LegalEntitiesTable } from './ui/LegalEntitiesTable' diff --git a/src/widgets/legal-entities-table/ui/LegalEntitiesTable.module.css b/src/widgets/legal-entities-table/ui/LegalEntitiesTable.module.css new file mode 100644 index 0000000..40910ba --- /dev/null +++ b/src/widgets/legal-entities-table/ui/LegalEntitiesTable.module.css @@ -0,0 +1,89 @@ +.tableWrap { + background: rgba(255, 255, 255, 0.04); + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: 24px; + padding: 24px; + overflow-x: auto; +} + +.table { + width: 100%; + border-collapse: collapse; +} + +.table th { + text-align: left; + font-size: 12px; + letter-spacing: 1.5px; + text-transform: uppercase; + color: var(--text-secondary); + font-weight: 500; + padding: 0 16px 18px; + white-space: nowrap; +} + +.table td { + padding: 16px; + border-top: 1px solid rgba(255, 255, 255, 0.06); + vertical-align: middle; + transition: background 0.2s ease; + font-size: 14px; + color: var(--text-primary); +} + +.table tr:hover td { + background: rgba(255, 255, 255, 0.04); +} + +.name { + font-weight: 600; + display: block; +} + +.subname { + display: block; + font-size: 12px; + color: var(--text-secondary); + margin-top: 2px; +} + +.mono { + font-family: var(--font-mono, monospace); + font-size: 13px; +} + +.status { + display: inline-block; + padding: 4px 10px; + border-radius: 999px; + font-size: 12px; + font-weight: 600; + background: rgba(74, 109, 255, 0.12); + color: #7c95ff; + white-space: nowrap; +} + +.kyc { + display: inline-block; + padding: 4px 10px; + border-radius: 999px; + font-size: 12px; + font-weight: 600; +} + +.kycOk { + background: rgba(0, 196, 140, 0.14); + color: #00c48c; +} + +.kycNo { + background: rgba(255, 90, 90, 0.14); + color: #ff5a5a; +} + +.state { + padding: 40px 16px; + text-align: center; + color: var(--text-secondary); + font-size: 14px; +} diff --git a/src/widgets/legal-entities-table/ui/LegalEntitiesTable.tsx b/src/widgets/legal-entities-table/ui/LegalEntitiesTable.tsx new file mode 100644 index 0000000..901e862 --- /dev/null +++ b/src/widgets/legal-entities-table/ui/LegalEntitiesTable.tsx @@ -0,0 +1,81 @@ +import { useOrganizations } from '@features/admin' +import styles from './LegalEntitiesTable.module.css' + +const STATUS_LABELS: Record = { + active: 'Активно', + blocked: 'Заблокировано', + inactive: 'Неактивно', +} + +function formatDate(value: string | null): string { + if (!value) return '—' + const d = new Date(value) + if (Number.isNaN(d.getTime())) return '—' + return d.toLocaleDateString('ru-RU') +} + +export function LegalEntitiesTable() { + const { data, isLoading, isError } = useOrganizations() + + if (isLoading) { + return
Загрузка...
+ } + + if (isError) { + return ( +
+
Не удалось загрузить список юридических лиц
+
+ ) + } + + if (!data || data.items.length === 0) { + return ( +
+
Юридические лица ещё не добавлены
+
+ ) + } + + return ( +
+ + + + + + + + + + + + + + + {data.items.map((org) => ( + + + + + + + + + + + ))} + +
НазваниеИННКППКонтактное лицоТелефонСтатусKYCСоздано
+ {org.name} + {org.short_name && {org.short_name}} + {org.inn}{org.kpp ?? '—'}{org.contact_person ?? '—'}{org.contact_phone ?? '—'} + {STATUS_LABELS[org.status] ?? org.status} + + + {org.kyc_verified ? 'Да' : 'Нет'} + + {formatDate(org.created_at)}
+
+ ) +} diff --git a/src/widgets/register-form/ui/IndividualForm.tsx b/src/widgets/register-form/ui/IndividualForm.tsx new file mode 100644 index 0000000..629ef52 --- /dev/null +++ b/src/widgets/register-form/ui/IndividualForm.tsx @@ -0,0 +1,84 @@ +import { FormField } from '@shared/ui' +import { PrimaryButton } from '@shared/ui' +import { Button } from '@shared/ui' +import { useRegisterForm } from '../model/useRegisterForm' +import styles from './RegisterForm.module.css' + +export function IndividualForm() { + const { + email, setEmail, + password, setPassword, + confirmPassword, setConfirmPassword, + verificationCode, setVerificationCode, + codeSent, + isLoadingCode, + isLoadingSubmit, + error, + handleRequestCode, + handleSubmit, + } = useRegisterForm() + + return ( +
+
+
+ + + +
+ +
+ + Код не пришёл + +
+
+ + {error &&

{error}

} + +
+ +
+ +

+ Нажимая «Создать», вы принимаете
+ Пользовательское соглашение и Политику конфиденциальности +

+
+ ) +} diff --git a/src/widgets/register-form/ui/LegalRegisterInfo.tsx b/src/widgets/register-form/ui/LegalRegisterInfo.tsx new file mode 100644 index 0000000..d455786 --- /dev/null +++ b/src/widgets/register-form/ui/LegalRegisterInfo.tsx @@ -0,0 +1,59 @@ +import { useState } from 'react' +import { PrimaryButton } from '@shared/ui' +import styles from './RegisterForm.module.css' + +const DOCS_EMAIL = 'company@elcsa.ru' + +const REQUIRED_DOCUMENTS = [ + 'Устав организации в действующей редакции', + 'Решение (протокол) о создании организации и о назначении руководителя', + 'Выписка по расчётному счёту из банка за последние шесть месяцев', + 'Выписка из Единого государственного реестра юридических лиц (ЕГРЮЛ)', + 'Идентификатор электронного документооборота (ЭДО)', + 'Реквизиты расчётного счёта: номер Р/С, БИК и наименование банка', +] + +export function LegalRegisterInfo() { + const [sent, setSent] = useState(false) + + if (sent) { + return ( +
+

Спасибо!

+

+ Мы получили уведомление об отправке документов. После проверки мы свяжемся с вами + по указанному адресу электронной почты. +

+
+ ) + } + + return ( +
+

+ Для регистрации юридического лица отправьте перечисленные ниже документы на нашу + электронную почту. После проверки мы свяжемся с вами для завершения регистрации. +

+ +
+ Необходимые документы +
    + {REQUIRED_DOCUMENTS.map((doc) => ( +
  • {doc}
  • + ))} +
+
+ +
+ Адрес для отправки документов + + {DOCS_EMAIL} + +
+ +
+ setSent(true)} /> +
+
+ ) +} diff --git a/src/widgets/register-form/ui/RegisterForm.module.css b/src/widgets/register-form/ui/RegisterForm.module.css index ea13ac9..b1d297c 100644 --- a/src/widgets/register-form/ui/RegisterForm.module.css +++ b/src/widgets/register-form/ui/RegisterForm.module.css @@ -26,6 +26,102 @@ line-height: 1.3; } +.typeSelect { + display: flex; + flex-direction: column; + gap: 12px; +} + +.typeSelect button { + width: 100%; +} + +.back { + background: none; + border: none; + padding: 0; + margin-bottom: 20px; + font-size: 13px; + font-weight: 600; + color: var(--text-secondary); + cursor: pointer; + font-family: var(--font-sans); +} + +.back:hover { + color: var(--text-primary); +} + +.legalInfo { + display: flex; + flex-direction: column; + gap: 20px; +} + +.legalIntro { + font-size: 14px; + line-height: 1.6; + color: var(--text-secondary); +} + +.docsBlock, +.emailBlock { + display: flex; + flex-direction: column; + gap: 10px; +} + +.docsLabel { + font-size: 13px; + font-weight: 700; + color: var(--text-primary); +} + +.docsList { + margin: 0; + padding-left: 20px; + display: flex; + flex-direction: column; + gap: 8px; +} + +.docsList li { + font-size: 13px; + line-height: 1.5; + color: var(--text-secondary); +} + +.emailLink { + font-size: 16px; + font-weight: 700; + color: var(--interactive); + text-decoration: none; +} + +.emailLink:hover { + text-decoration: underline; +} + +.legalDone { + display: flex; + flex-direction: column; + gap: 12px; + text-align: center; + padding: 12px 0; +} + +.legalDoneTitle { + font-size: 20px; + font-weight: 700; + color: var(--text-primary); +} + +.legalDoneText { + font-size: 14px; + line-height: 1.6; + color: var(--text-secondary); +} + .twoCol { display: grid; grid-template-columns: 1fr; diff --git a/src/widgets/register-form/ui/RegisterForm.tsx b/src/widgets/register-form/ui/RegisterForm.tsx index 24f9313..36da512 100644 --- a/src/widgets/register-form/ui/RegisterForm.tsx +++ b/src/widgets/register-form/ui/RegisterForm.tsx @@ -1,90 +1,39 @@ -import { FormField } from '@shared/ui' -import { PrimaryButton } from '@shared/ui' +import { useState } from 'react' import { Button } from '@shared/ui' import logo from '@shared/assets/logo-full-white.png' -import { useRegisterForm } from '../model/useRegisterForm' +import { IndividualForm } from './IndividualForm' +import { LegalRegisterInfo } from './LegalRegisterInfo' import styles from './RegisterForm.module.css' +type RegisterType = 'individual' | 'legal' + export function RegisterForm() { - const { - email, setEmail, - password, setPassword, - confirmPassword, setConfirmPassword, - verificationCode, setVerificationCode, - codeSent, - isLoadingCode, - isLoadingSubmit, - error, - handleRequestCode, - handleSubmit, - } = useRegisterForm() + const [type, setType] = useState(null) return ( -
+
ЭКСА

Создать кошелёк ЭКСА

-
-
- - - -
- -
- + - Код не пришёл -
-
- - {error &&

{error}

} - -
- -
- -

- Нажимая «Создать», вы принимаете
- Пользовательское соглашение и Политику конфиденциальности -

- + ) : ( + <> + + {type === 'individual' ? : } + + )} +
) } diff --git a/tsconfig.tsbuildinfo b/tsconfig.tsbuildinfo index 18ca05a..e60d7a9 100644 --- a/tsconfig.tsbuildinfo +++ b/tsconfig.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/main.tsx","./src/vite-env.d.ts","./src/app/app.tsx","./src/app/providers/guestroute.tsx","./src/app/providers/protectedroute.tsx","./src/app/providers/queryprovider.tsx","./src/app/providers/routerprovider.tsx","./src/app/providers/scrolltotop.tsx","./src/app/providers/index.ts","./src/entities/commission/index.ts","./src/entities/commission/model/tiers.ts","./src/entities/commission/ui/commissiontable.tsx","./src/features/auth/index.ts","./src/features/auth/api/profileapi.ts","./src/features/auth/api/registrationapi.ts","./src/features/auth/hooks/useauth.ts","./src/features/auth/hooks/useisauthenticated.ts","./src/features/auth/hooks/useme.ts","./src/features/auth/hooks/useupdatephone.ts","./src/features/auth/hooks/useuploadavatar.ts","./src/features/kyc/api/kycapi.ts","./src/features/payment/index.ts","./src/features/payment/api/paymentapi.ts","./src/features/payment/hooks/usecreateorder.ts","./src/features/payment/hooks/useorders.ts","./src/features/payment/hooks/usepaymentconfig.ts","./src/features/payment/hooks/usepaymentquote.ts","./src/features/payment/hooks/usepaymentquotebyrub.ts","./src/features/payment/model/usecurrencyconversion.ts","./src/features/wallet/index.ts","./src/features/wallet/api/walletapi.ts","./src/features/wallet/model/usewalletdata.ts","./src/pages/bridge/index.ts","./src/pages/bridge/ui/bridgepage.tsx","./src/pages/converter/index.ts","./src/pages/converter/ui/converterpage.tsx","./src/pages/converter-test/index.ts","./src/pages/converter-test/ui/convertertestpage.tsx","./src/pages/home/index.ts","./src/pages/home/ui/homepage.tsx","./src/pages/kyc/index.ts","./src/pages/kyc/ui/kycpage.tsx","./src/pages/login/index.ts","./src/pages/login/ui/loginpage.tsx","./src/pages/politika-cookie/index.ts","./src/pages/politika-cookie/ui/politikacookiepage.tsx","./src/pages/politika-personalnyh-dannyh/index.ts","./src/pages/politika-personalnyh-dannyh/ui/politikapage.tsx","./src/pages/profile/index.ts","./src/pages/profile/ui/profilepage.tsx","./src/pages/publichnaya-oferta/index.ts","./src/pages/publichnaya-oferta/ui/publichnayaofertapage.tsx","./src/pages/reestr-pd-rkn/index.ts","./src/pages/reestr-pd-rkn/ui/reestrypage.tsx","./src/pages/register/index.ts","./src/pages/register/ui/registerpage.tsx","./src/pages/register-test/index.ts","./src/pages/register-test/ui/registertestpage.tsx","./src/pages/restore-password/index.ts","./src/pages/restore-password/ui/restorepasswordpage.tsx","./src/pages/seed-phrase/index.ts","./src/pages/seed-phrase/ui/seedphrasepage.tsx","./src/pages/soglasie-personalnyh-dannyh/index.ts","./src/pages/soglasie-personalnyh-dannyh/ui/soglasiepage.tsx","./src/pages/swap/index.ts","./src/pages/swap/ui/swappage.tsx","./src/pages/transactions/index.ts","./src/pages/transactions/ui/transactionspage.tsx","./src/pages/wallet/index.ts","./src/pages/wallet/ui/walletpage.tsx","./src/shared/api/base.ts","./src/shared/api/csrf.ts","./src/shared/api/tokenstore.ts","./src/shared/api/types.ts","./src/shared/assets/coins/index.ts","./src/shared/config/constants.ts","./src/shared/config/env.ts","./src/shared/config/routes.ts","./src/shared/lib/hooks/usedebounce.ts","./src/shared/lib/hooks/uselocalstorage.ts","./src/shared/lib/utils/baseunits.ts","./src/shared/lib/utils/cn.ts","./src/shared/lib/utils/truncatedecimals.ts","./src/shared/types/index.ts","./src/shared/ui/index.ts","./src/shared/ui/button/button.tsx","./src/shared/ui/button/index.ts","./src/shared/ui/convertfield/convertfield.tsx","./src/shared/ui/convertfield/index.ts","./src/shared/ui/directionswapbutton/directionswapbutton.tsx","./src/shared/ui/directionswapbutton/index.ts","./src/shared/ui/formfield/formfield.tsx","./src/shared/ui/formfield/index.ts","./src/shared/ui/notification/notification.tsx","./src/shared/ui/notification/index.ts","./src/shared/ui/pill/pill.tsx","./src/shared/ui/pill/index.ts","./src/shared/ui/primarybutton/primarybutton.tsx","./src/shared/ui/primarybutton/index.ts","./src/shared/ui/title/title.tsx","./src/shared/ui/tokenicon/tokenicon.tsx","./src/shared/ui/tokenicon/index.ts","./src/widgets/about/index.ts","./src/widgets/about/ui/about.tsx","./src/widgets/balance-card/index.ts","./src/widgets/balance-card/ui/balancecard.tsx","./src/widgets/bridge-form/index.ts","./src/widgets/bridge-form/ui/bridgeconfirmmodal.tsx","./src/widgets/bridge-form/ui/bridgeform.tsx","./src/widgets/bridge-form/ui/networkselect.tsx","./src/widgets/converter-page/index.ts","./src/widgets/converter-page/model/useconvertersection.ts","./src/widgets/converter-page/ui/agreementcheck.tsx","./src/widgets/converter-page/ui/convertersection.tsx","./src/widgets/currency-converter/index.ts","./src/widgets/currency-converter/ui/agreementcheckbox.tsx","./src/widgets/currency-converter/ui/converter.tsx","./src/widgets/footer/index.ts","./src/widgets/footer/ui/footer.tsx","./src/widgets/header/index.ts","./src/widgets/header/ui/header.tsx","./src/widgets/hero/index.ts","./src/widgets/hero/lib/usecountdown.ts","./src/widgets/hero/ui/conversionflow.tsx","./src/widgets/hero/ui/countdown.tsx","./src/widgets/hero/ui/exchangecard.tsx","./src/widgets/hero/ui/hero.tsx","./src/widgets/kyc-verification/index.ts","./src/widgets/kyc-verification/model/usekyc.ts","./src/widgets/kyc-verification/ui/kycmodal.tsx","./src/widgets/kyc-verification/ui/kycwidget.tsx","./src/widgets/login-form/index.ts","./src/widgets/login-form/model/useloginform.ts","./src/widgets/login-form/ui/loginform.tsx","./src/widgets/networks-table/index.ts","./src/widgets/networks-table/model/networks.ts","./src/widgets/networks-table/ui/networkstable.tsx","./src/widgets/profile/index.ts","./src/widgets/profile/ui/avatarcropmodal.tsx","./src/widgets/profile/ui/profileavatar.tsx","./src/widgets/profile/ui/profilesection.tsx","./src/widgets/profile/ui/getcroppedimg.ts","./src/widgets/receive-modal/index.ts","./src/widgets/receive-modal/ui/receivemodal.tsx","./src/widgets/register-form/index.ts","./src/widgets/register-form/model/useregisterform.ts","./src/widgets/register-form/ui/registerform.tsx","./src/widgets/restore-password-form/index.ts","./src/widgets/restore-password-form/ui/restorepasswordform.tsx","./src/widgets/seed-phrase/index.ts","./src/widgets/seed-phrase/model/useseedphrase.ts","./src/widgets/seed-phrase/ui/seedphrasewidget.tsx","./src/widgets/send-modal/index.ts","./src/widgets/send-modal/model/sendtypes.ts","./src/widgets/send-modal/ui/sendmodal.tsx","./src/widgets/swap-bridge-tabs/index.ts","./src/widgets/swap-bridge-tabs/ui/swapbridgetabs.tsx","./src/widgets/swap-form/index.ts","./src/widgets/swap-form/model/useswapform.ts","./src/widgets/swap-form/ui/raterow.tsx","./src/widgets/swap-form/ui/swapcard.tsx","./src/widgets/swap-form/ui/swapconfirmmodal.tsx","./src/widgets/swap-form/ui/swapdirectionbutton.tsx","./src/widgets/swap-form/ui/swapform.tsx","./src/widgets/swap-form/ui/swapinfopanel.tsx","./src/widgets/swap-form/ui/tokenselect.tsx","./src/widgets/swap-form/ui/trxconfirmmodal.tsx","./src/widgets/token-table/index.ts","./src/widgets/token-table/model/tokens.ts","./src/widgets/token-table/model/usechaintokenrows.ts","./src/widgets/token-table/ui/tokentable.tsx","./src/widgets/transactions-list/index.ts","./src/widgets/transactions-list/model/format.ts","./src/widgets/transactions-list/model/paymentstatuslabels.ts","./src/widgets/transactions-list/ui/copybutton.tsx","./src/widgets/transactions-list/ui/orderaccordion.tsx","./src/widgets/transactions-list/ui/statusbadge.tsx","./src/widgets/transactions-list/ui/transactionslist.tsx","./src/widgets/wallet-chain-tabs/index.ts","./src/widgets/wallet-chain-tabs/ui/walletchaintabs.tsx","./src/widgets/wallet-header/index.ts","./src/widgets/wallet-header/ui/walletheader.tsx","./src/widgets/wallet-layout/index.ts","./src/widgets/wallet-layout/ui/walletlayout.tsx"],"version":"5.6.3"} \ No newline at end of file +{"root":["./src/main.tsx","./src/vite-env.d.ts","./src/app/app.tsx","./src/app/providers/guestroute.tsx","./src/app/providers/protectedroute.tsx","./src/app/providers/queryprovider.tsx","./src/app/providers/routerprovider.tsx","./src/app/providers/scrolltotop.tsx","./src/app/providers/index.ts","./src/entities/commission/index.ts","./src/entities/commission/model/tiers.ts","./src/entities/commission/ui/commissiontable.tsx","./src/features/admin/index.ts","./src/features/admin/api/adminapi.ts","./src/features/admin/hooks/useadminauth.ts","./src/features/admin/hooks/useadminlogin.ts","./src/features/admin/hooks/useadminlogout.ts","./src/features/admin/hooks/usecreateorganization.ts","./src/features/admin/hooks/useorganizations.ts","./src/features/admin/model/types.ts","./src/features/auth/index.ts","./src/features/auth/api/profileapi.ts","./src/features/auth/api/registrationapi.ts","./src/features/auth/hooks/useauth.ts","./src/features/auth/hooks/useisauthenticated.ts","./src/features/auth/hooks/useme.ts","./src/features/auth/hooks/useupdatephone.ts","./src/features/auth/hooks/useuploadavatar.ts","./src/features/kyc/api/kycapi.ts","./src/features/payment/index.ts","./src/features/payment/api/paymentapi.ts","./src/features/payment/hooks/usecreateorder.ts","./src/features/payment/hooks/useorders.ts","./src/features/payment/hooks/usepaymentconfig.ts","./src/features/payment/hooks/usepaymentquote.ts","./src/features/payment/hooks/usepaymentquotebyrub.ts","./src/features/payment/model/usecurrencyconversion.ts","./src/features/wallet/index.ts","./src/features/wallet/api/walletapi.ts","./src/features/wallet/model/usewalletdata.ts","./src/pages/admin/index.ts","./src/pages/admin/ui/adminpage.tsx","./src/pages/bridge/index.ts","./src/pages/bridge/ui/bridgepage.tsx","./src/pages/converter/index.ts","./src/pages/converter/ui/converterpage.tsx","./src/pages/converter-test/index.ts","./src/pages/converter-test/ui/convertertestpage.tsx","./src/pages/home/index.ts","./src/pages/home/ui/homepage.tsx","./src/pages/kyc/index.ts","./src/pages/kyc/ui/kycpage.tsx","./src/pages/login/index.ts","./src/pages/login/ui/loginpage.tsx","./src/pages/politika-cookie/index.ts","./src/pages/politika-cookie/ui/politikacookiepage.tsx","./src/pages/politika-personalnyh-dannyh/index.ts","./src/pages/politika-personalnyh-dannyh/ui/politikapage.tsx","./src/pages/profile/index.ts","./src/pages/profile/ui/profilepage.tsx","./src/pages/publichnaya-oferta/index.ts","./src/pages/publichnaya-oferta/ui/publichnayaofertapage.tsx","./src/pages/reestr-pd-rkn/index.ts","./src/pages/reestr-pd-rkn/ui/reestrypage.tsx","./src/pages/register/index.ts","./src/pages/register/ui/registerpage.tsx","./src/pages/register-test/index.ts","./src/pages/register-test/ui/registertestpage.tsx","./src/pages/restore-password/index.ts","./src/pages/restore-password/ui/restorepasswordpage.tsx","./src/pages/seed-phrase/index.ts","./src/pages/seed-phrase/ui/seedphrasepage.tsx","./src/pages/soglasie-personalnyh-dannyh/index.ts","./src/pages/soglasie-personalnyh-dannyh/ui/soglasiepage.tsx","./src/pages/swap/index.ts","./src/pages/swap/ui/swappage.tsx","./src/pages/transactions/index.ts","./src/pages/transactions/ui/transactionspage.tsx","./src/pages/wallet/index.ts","./src/pages/wallet/ui/walletpage.tsx","./src/shared/api/base.ts","./src/shared/api/csrf.ts","./src/shared/api/tokenstore.ts","./src/shared/api/types.ts","./src/shared/assets/coins/index.ts","./src/shared/config/constants.ts","./src/shared/config/env.ts","./src/shared/config/routes.ts","./src/shared/lib/hooks/usedebounce.ts","./src/shared/lib/hooks/uselocalstorage.ts","./src/shared/lib/utils/baseunits.ts","./src/shared/lib/utils/cn.ts","./src/shared/lib/utils/truncatedecimals.ts","./src/shared/types/index.ts","./src/shared/ui/index.ts","./src/shared/ui/button/button.tsx","./src/shared/ui/button/index.ts","./src/shared/ui/convertfield/convertfield.tsx","./src/shared/ui/convertfield/index.ts","./src/shared/ui/directionswapbutton/directionswapbutton.tsx","./src/shared/ui/directionswapbutton/index.ts","./src/shared/ui/formfield/formfield.tsx","./src/shared/ui/formfield/index.ts","./src/shared/ui/notification/notification.tsx","./src/shared/ui/notification/index.ts","./src/shared/ui/pill/pill.tsx","./src/shared/ui/pill/index.ts","./src/shared/ui/primarybutton/primarybutton.tsx","./src/shared/ui/primarybutton/index.ts","./src/shared/ui/title/title.tsx","./src/shared/ui/tokenicon/tokenicon.tsx","./src/shared/ui/tokenicon/index.ts","./src/widgets/about/index.ts","./src/widgets/about/ui/about.tsx","./src/widgets/add-legal-entity-modal/index.ts","./src/widgets/add-legal-entity-modal/model/useaddlegalentityform.ts","./src/widgets/add-legal-entity-modal/ui/addlegalentitymodal.tsx","./src/widgets/admin-login-form/index.ts","./src/widgets/admin-login-form/model/useadminloginform.ts","./src/widgets/admin-login-form/ui/adminloginform.tsx","./src/widgets/balance-card/index.ts","./src/widgets/balance-card/ui/balancecard.tsx","./src/widgets/bridge-form/index.ts","./src/widgets/bridge-form/ui/bridgeconfirmmodal.tsx","./src/widgets/bridge-form/ui/bridgeform.tsx","./src/widgets/bridge-form/ui/networkselect.tsx","./src/widgets/converter-page/index.ts","./src/widgets/converter-page/model/useconvertersection.ts","./src/widgets/converter-page/ui/agreementcheck.tsx","./src/widgets/converter-page/ui/convertersection.tsx","./src/widgets/currency-converter/index.ts","./src/widgets/currency-converter/ui/agreementcheckbox.tsx","./src/widgets/currency-converter/ui/converter.tsx","./src/widgets/footer/index.ts","./src/widgets/footer/ui/footer.tsx","./src/widgets/header/index.ts","./src/widgets/header/ui/header.tsx","./src/widgets/hero/index.ts","./src/widgets/hero/lib/usecountdown.ts","./src/widgets/hero/ui/conversionflow.tsx","./src/widgets/hero/ui/countdown.tsx","./src/widgets/hero/ui/exchangecard.tsx","./src/widgets/hero/ui/hero.tsx","./src/widgets/kyc-verification/index.ts","./src/widgets/kyc-verification/model/usekyc.ts","./src/widgets/kyc-verification/ui/kycmodal.tsx","./src/widgets/kyc-verification/ui/kycwidget.tsx","./src/widgets/legal-entities-table/index.ts","./src/widgets/legal-entities-table/ui/legalentitiestable.tsx","./src/widgets/login-form/index.ts","./src/widgets/login-form/model/useloginform.ts","./src/widgets/login-form/ui/loginform.tsx","./src/widgets/networks-table/index.ts","./src/widgets/networks-table/model/networks.ts","./src/widgets/networks-table/ui/networkstable.tsx","./src/widgets/profile/index.ts","./src/widgets/profile/ui/avatarcropmodal.tsx","./src/widgets/profile/ui/profileavatar.tsx","./src/widgets/profile/ui/profilesection.tsx","./src/widgets/profile/ui/getcroppedimg.ts","./src/widgets/receive-modal/index.ts","./src/widgets/receive-modal/ui/receivemodal.tsx","./src/widgets/register-form/index.ts","./src/widgets/register-form/model/useregisterform.ts","./src/widgets/register-form/ui/individualform.tsx","./src/widgets/register-form/ui/legalregisterinfo.tsx","./src/widgets/register-form/ui/registerform.tsx","./src/widgets/restore-password-form/index.ts","./src/widgets/restore-password-form/ui/restorepasswordform.tsx","./src/widgets/seed-phrase/index.ts","./src/widgets/seed-phrase/model/useseedphrase.ts","./src/widgets/seed-phrase/ui/seedphrasewidget.tsx","./src/widgets/send-modal/index.ts","./src/widgets/send-modal/model/sendtypes.ts","./src/widgets/send-modal/ui/sendmodal.tsx","./src/widgets/swap-bridge-tabs/index.ts","./src/widgets/swap-bridge-tabs/ui/swapbridgetabs.tsx","./src/widgets/swap-form/index.ts","./src/widgets/swap-form/model/useswapform.ts","./src/widgets/swap-form/ui/raterow.tsx","./src/widgets/swap-form/ui/swapcard.tsx","./src/widgets/swap-form/ui/swapconfirmmodal.tsx","./src/widgets/swap-form/ui/swapdirectionbutton.tsx","./src/widgets/swap-form/ui/swapform.tsx","./src/widgets/swap-form/ui/swapinfopanel.tsx","./src/widgets/swap-form/ui/tokenselect.tsx","./src/widgets/swap-form/ui/trxconfirmmodal.tsx","./src/widgets/token-table/index.ts","./src/widgets/token-table/model/tokens.ts","./src/widgets/token-table/model/usechaintokenrows.ts","./src/widgets/token-table/ui/tokentable.tsx","./src/widgets/transactions-list/index.ts","./src/widgets/transactions-list/model/format.ts","./src/widgets/transactions-list/model/paymentstatuslabels.ts","./src/widgets/transactions-list/ui/copybutton.tsx","./src/widgets/transactions-list/ui/orderaccordion.tsx","./src/widgets/transactions-list/ui/statusbadge.tsx","./src/widgets/transactions-list/ui/transactionslist.tsx","./src/widgets/wallet-chain-tabs/index.ts","./src/widgets/wallet-chain-tabs/ui/walletchaintabs.tsx","./src/widgets/wallet-header/index.ts","./src/widgets/wallet-header/ui/walletheader.tsx","./src/widgets/wallet-layout/index.ts","./src/widgets/wallet-layout/ui/walletlayout.tsx"],"version":"5.6.3"} \ No newline at end of file