PageSourceSearch

https://luyentu.com/assets/Categories.DF9LAFRu.js

js luyentu.com collected 2026-10-02 01:34:59 UTC 27,282 bytes, 1 lines download raw bytes

1import{r,m as o,j as e,M as ye,e as we,f as Ce,D as Se,g as ve,h as Fe,V as q,ap as be,aq as je,a1 as X,B as p,J as ke,K as _,A as Me,aR as I,F as Y,E as Pe,v as O,I as x,aS as U,a3 as Ee,p as w,aT as Pt,C as V,Q as Re,aU as Vt,ar as Ot,Y as xe,u as Ht,W as Dt,aV as st,S as Kt,aW as nt,aX as Ut,w as at,a6 as rt,aY as ot,aZ as it,G as qt,aO as ct,a_ as $t}from"./index.BvQk7nKY.js";import{F as _e,C as lt}from"./FolderCard.CAD7pXxd.js";import{F as fe}from"./form-label.BYHbz9_B.js";import{T as Gt}from"./textarea.Dh7GL6FG.js";import{C as Qt}from"./CategoryViewModal.C60jOXvv.js";import{I as gt,b as pt}from"./input-element.B1ALNy2f.js";import{R as Xt,a as dt}from"./radio.C5Qy85sx.js";import{P as Yt,W as Jt}from"./Pagination.XY1zAcRH.js";import{C as Zt}from"./container.BaFZmVKn.js";import{T as es,a as ts,b as ht,c as ss,d as ut}from"./tab-panels.DNejKblh.js";import{H as ee}from"./heading.CR44K93P.js";import"./index.ujSNhaRa.js";import"./checkbox.HrFFF-K9.js";import"./progress.La7AQBTU.js";import"./xlsx.Bb4-Qvg-.js";import"./table-container.DRi5DEOG.js";import"./tr.C29cOhQ5.js";const ns=({isOpen:b,onClose:f,category:m,onSave:N})=>{const[a,d]=r.useState({name:"",description:"",icon:"fas fa-book"}),[A,C]=r.useState(!1),S=["📚","📖","📝","✏️","📕","⭐","🎯","💡","🔥","💎","🎓","🌟"];r.useEffect(()=>{d(m?{name:m.name||"",description:m.description||"",icon:m.icon||"fas fa-book"}:{name:"",description:"",icon:"fas fa-book"})},[m,b]);const v=async c=>{c.preventDefault(),C(!0),await N(a),C(!1)},F=c=>{d({...a,icon:c})},j=o("gray.100","gray.700"),W=o("gray.200","gray.600"),k=o("blue.100","blue.600"),h=o("blue.500","blue.200");return e.jsxs(ye,{isOpen:b,onClose:f,size:"md",isCentered:!0,zIndex:10100,children:[e.jsx(we,{}),e.jsxs(Ce,{as:"form",onSubmit:v,children:[e.jsx(Se,{children:m?"Chỉnh sửa bộ từ":"Tạo bộ từ"}),e.jsx(ve,{}),e.jsx(Fe,{pb:6,children:e.jsxs(q,{spacing:4,children:[e.jsxs(be,{isRequired:!0,children:[e.jsx(fe,{children:"Tên bộ từ"}),e.jsx(je,{value:a.name,onChange:c=>d({...a,name:c.target.value}),placeholder:"VD: IELTS Speaking"})]}),e.jsxs(be,{children:[e.jsx(fe,{children:"Mô tả"}),e.jsx(Gt,{value:a.description,onChange:c=>d({...a,description:c.target.value}),placeholder:"Mô tả về bộ từ này...",rows:3})]}),e.jsxs(be,{children:[e.jsx(fe,{children:"Biểu tượng"}),e.jsx(X,{columns:6,spacing:2,children:S.map(c=>e.jsx(p,{as:"button",type:"button",height:"40px",display:"flex",alignItems:"center",justifyContent:"center",fontSize:"xl",borderRadius:"md",bg:a.icon===c?k:j,borderWidth:"2px",borderColor:a.icon===c?h:"transparent",_hover:{bg:W},onClick:()=>F(c),transition:"all 0.2s",children:c},c))})]})]})}),e.jsxs(ke,{children:[e.jsx(_,{variant:"ghost",mr:3,onClick:f,children:"Hủy"}),e.jsx(_,{colorScheme:"blue",type:"submit",isLoading:A,loadingText:"Đang lưu",children:m?"Cập nhật":"Tạo mới"})]})]})]})};function as({isOpen:b,onClose:f,selectedCategoryIds:m,onSuccess:N}){const[a,d]=r.useState([]),[A,C]=r.useState(!1),[S,v]=r.useState(!1),[F,j]=r.useState(null),[W,k]=r.useState(!1),[h,c]=r.useState(""),[E,R]=r.useState(!1),y=Me(),M=o("white","#1f2937"),te=o("gray.200","whiteAlpha.200"),se=o("gray.50","#243043"),ne=o("gray.100","#334155"),J=o("blue.50","rgba(59, 130, 246, 0.22)"),ae=o("blue.400","blue.300"),$=o("green.50","rgba(35, 172, 56, 0.22)"),i=o("green.100","rgba(35, 172, 56, 0.3)"),H=o("green.300","green.300"),Z=o("white","#111827"),u=o("gray.200","whiteAlpha.200"),z=o("gray.600","gray.300"),Te=o("gray.500","gray.400");r.useEffect(()=>{b&&(re(),j(null),k(!1),c(""))},[b]);const re=async()=>{C(!0);try{const g=await I.getAll(),B=g.data?.data||g.data||[];d(Array.isArray(B)?B:[])}catch{y({title:"Lỗi tải thư mục",status:"error",duration:3e3})}finally{C(!1)}},oe=async()=>{if(h.trim()){R(!0);try{const g=await I.create({name:h.trim()}),B=g.data?.data||g.data;d(Ie=>[...Ie,B]),j(B.id),c(""),k(!1),y({title:"Đã tạo thư mục mới",status:"success",duration:2e3})}catch(g){y({title:"Lỗi tạo thư mục",description:g.response?.data?.message||"Vui lòng thử lại",status:"error",duration:3e3})}finally{R(!1)}}},ie=async()=>
1{if(F){v(!0);try{await I.addCategories(F,m),y({title:"Đã thêm vào thư mục",status:"success",duration:3e3}),N?.(),f()}catch(g){y({title:"Lỗi thêm vào thư mục",description:g.response?.data?.message||"Vui lòng thử lại",status:"error",duration:3e3})}finally{v(!1)}}};return e.jsxs(ye,{isOpen:b,onClose:f,isCentered:!0,size:"md",children:[e.jsx(we,{backdropFilter:"blur(4px)"}),e.jsxs(Ce,{borderRadius:"xl",bg:M,border:"1px solid",borderColor:te,boxShadow:"2xl",children:[e.jsx(Se,{children:"Chọn thư mục"}),e.jsx(ve,{}),e.jsx(Fe,{maxH:"400px",overflowY:"auto",children:A?e.jsx(Y,{justify:"center",p:4,children:e.jsx(Pe,{})}):e.jsxs(q,{spacing:3,align:"stretch",children:[W?e.jsxs(O,{spacing:2,children:[e.jsxs(gt,{size:"md",children:[e.jsx(pt,{children:e.jsx(x,{as:U,color:"blue.500"})}),e.jsx(je,{placeholder:"Tên thư mục mới...",value:h,onChange:g=>c(g.target.value),onKeyDown:g=>g.key==="Enter"&&oe(),autoFocus:!0,bg:Z,borderColor:u})]}),e.jsx(_,{colorScheme:"green",size:"md",onClick:oe,isLoading:E,isDisabled:!h.trim(),children:"Tạo"}),e.jsx(_,{variant:"ghost",size:"md",onClick:()=>{k(!1),c("")},children:"Hủy"})]}):e.jsxs(p,{p:3,borderRadius:"lg",border:"2px dashed",borderColor:H,bg:$,cursor:"pointer",_hover:{bg:i,borderColor:H},onClick:()=>k(!0),display:"flex",alignItems:"center",transition:"all 0.2s",children:[e.jsx(x,{as:Ee,color:"green.500",mr:3,boxSize:5}),e.jsx(w,{fontWeight:"500",color:"green.500",children:"Tạo thư mục mới"})]}),a.length>0&&e.jsxs(w,{fontSize:"sm",color:z,mt:2,children:["Chọn thư mục để thêm ",m.length," bộ từ:"]}),a.map(g=>{const B=F===g.id;return e.jsxs(p,{p:3,borderRadius:"lg",border:"2px solid",borderColor:B?ae:"transparent",bg:B?J:se,cursor:"pointer",_hover:{bg:B?J:ne},onClick:()=>j(g.id),display:"flex",alignItems:"center",transition:"all 0.2s",children:[e.jsx(x,{as:U,color:"blue.500",mr:3,boxSize:5}),e.jsx(w,{fontWeight:"500",flex:1,children:g.name}),B&&e.jsx(x,{as:Pt,color:"blue.500"})]},g.id)}),a.length===0&&!W&&e.jsx(w,{color:Te,textAlign:"center",py:2,fontSize:"sm",children:"Chưa có thư mục nào."})]})}),e.jsxs(ke,{children:[e.jsx(_,{variant:"ghost",onClick:f,mr:3,children:"Hủy"}),e.jsx(_,{colorScheme:"blue",onClick:ie,isLoading:S,isDisabled:!F,children:"Xác nhận"})]})]})]})}function rs({isOpen:b,onClose:f,category:m,onSuccess:N}){const[a,d]=r.useState("new"),[A,C]=r.useState([]),[S,v]=r.useState(""),[F,j]=r.useState(!1),[W,k]=r.useState(!1),h=Me(),c=o("white","#1f2937"),E=o("gray.200","whiteAlpha.200"),R=o("gray.50","#243043"),y=o("gray.500","gray.300"),M=o("gray.700","white"),te=o("blue.50","rgba(59, 130, 246, 0.22)"),se=o("blue.300","blue.300"),ne=o("green.50","rgba(35, 172, 56, 0.22)"),J=o("green.300","green.300"),ae=o("white","#111827"),$=o("gray.200","whiteAlpha.200");r.useEffect(()=>{b&&a==="existing"&&A.length===0&&i()},[b,a]);const i=async()=>{k(!0);try{const u=await V.getAll(),z=u.data?.data||u.data||[];C(Array.isArray(z)?z:[])}catch{C([])}finally{k(!1)}},H=async()=>{if(m){j(!0);try{if(a==="new")await V.copy(m.id),h({title:"Đã sao chép bộ từ mới",status:"success",duration:3e3});else{if(!S){h({title:"Vui lòng chọn bộ từ đích",status:"warning",duration:2e3}),j(!1);return}const z=(await V.copyToExisting(m.id,S)).data?.data||{};h({title:`Đã thêm ${z.added||0} từ`,description:z.skipped>0?`Bỏ qua ${z.skipped} từ trùng`:void 0,status:"success",duration:3e3})}N?.(),f()}catch(u){u.response?.status===403?(N?.({wordLimitError:u.response?.data?.message}),f()):h({title:"Lỗi sao chép",description:u.response?.data?.message||"Không thể sao chép",status:"error",duration:4e3})}finally{j(!1)}}},Z=()=>{d("new"),v(""),f()};return e.jsxs(ye,{isOpen:b,onClose:Z,isCentered:!0,size:"md",children:[e.jsx(we,{backdropFilter:"blur(4px)"}),e.jsxs(Ce,{borderRadius:"2xl",bg:c,border:"1px solid",borderColor:E,boxShadow:"2xl",children:[e.jsx(Se,{children:e.jsxs(O,{children:[e.jsx(x,{as:Re,color:"blue.500"}),e.jsx(w,{children:"Sao chép bộ từ"})]})}),e.jsx(ve,{}),e.jsx(Fe,{children:e.jsxs(q,{spacing:4,align:"stretch",children:[e.jsxs(w,{fontSize:"sm",color:y,children:["Bộ từ: ",e.jsx("strong",{children:m?.name})," (",m?.wordCount||0," từ)"]}),e.jsx(Xt,{value:a,onChange:d,children:e.jsxs(q,{spacing:3,align:"stretch",children:[e.jsxs(p,{p:3,borderRadius:"lg",bg:a==="new"?te:R,borderWidth:"2px",borderColor:a==="new"?se:"transparent",curs
1or:"pointer",onClick:()=>d("new"),transition:"all 0.2s",children:[e.jsxs(O,{children:[e.jsx(dt,{value:"new",colorScheme:"blue"}),e.jsx(x,{as:Vt,color:"blue.500"}),e.jsx(w,{fontWeight:"600",color:M,children:"Sao chép thành bộ từ mới"})]}),e.jsx(w,{fontSize:"xs",color:y,ml:10,children:"Tạo bộ từ riêng với toàn bộ từ vựng"})]}),e.jsxs(p,{p:3,borderRadius:"lg",bg:a==="existing"?ne:R,borderWidth:"2px",borderColor:a==="existing"?J:"transparent",cursor:"pointer",onClick:()=>d("existing"),transition:"all 0.2s",children:[e.jsxs(O,{children:[e.jsx(dt,{value:"existing",colorScheme:"green"}),e.jsx(x,{as:U,color:"green.500"}),e.jsx(w,{fontWeight:"600",color:M,children:"Thêm từ vào bộ sẵn có"})]}),e.jsx(w,{fontSize:"xs",color:y,ml:10,children:"Ghép từ mới vào bộ từ đã có, tự bỏ qua các từ trùng"})]})]})}),a==="existing"&&e.jsx(p,{children:W?e.jsxs(O,{justify:"center",py:3,children:[e.jsx(Pe,{size:"sm"}),e.jsx(w,{fontSize:"sm",children:"Đang tải..."})]}):e.jsx(Ot,{placeholder:"Chọn bộ từ đích...",value:S,onChange:u=>v(u.target.value),borderRadius:"lg",bg:ae,borderColor:$,children:A.map(u=>e.jsxs("option",{value:u.id,children:[u.name," (",u.wordCount||u.vocabularies?.length||0," từ)"]},u.id))})})]})}),e.jsxs(ke,{gap:2,children:[e.jsx(_,{variant:"ghost",onClick:Z,children:"Hủy"}),e.jsx(_,{colorScheme:a==="new"?"blue":"green",onClick:H,isLoading:F,leftIcon:e.jsx(x,{as:Re}),children:a==="new"?"Sao chép":"Thêm từ"})]})]})]})}const os="_button_owlma_3",is="_content_owlma_66",cs="_icon_owlma_76",ls="_ripple_owlma_84",he={button:os,content:is,icon:cs,ripple:ls},P=({children:b,variant:f="green",size:m="md",fullWidth:N=!1,loading:a=!1,disabled:d=!1,onClick:A,leftIcon:C,rightIcon:S,className:v="",...F})=>{const[j,W]=r.useState({x:0,y:0,show:!1}),k={green:{bg:"#23ac38",bgHover:"#4fc766",shadow:"#1f8f31",text:"white",glow:"rgba(35, 172, 56, 0.4)"},blue:{bg:"#1cb0f6",bgHover:"#49c0f8",shadow:"#1899d6",text:"white",glow:"rgba(28, 176, 246, 0.4)"},purple:{bg:"#ce82ff",bgHover:"#dda0ff",shadow:"#a855f7",text:"white",glow:"rgba(206, 130, 255, 0.4)"},yellow:{bg:"#ffc800",bgHover:"#ffd633",shadow:"#e6b400",text:"#3c3c3c",glow:"rgba(255, 200, 0, 0.4)"},orange:{bg:"#ff9600",bgHover:"#ffab33",shadow:"#ea7e00",text:"white",glow:"rgba(255, 150, 0, 0.4)"},red:{bg:"#ff4b4b",bgHover:"#ff6b6b",shadow:"#ea2b2b",text:"white",glow:"rgba(255, 75, 75, 0.4)"},ghost:{bg:"transparent",bgHover:"rgba(28, 176, 246, 0.1)",shadow:"transparent",text:"#1cb0f6",glow:"transparent",border:"#1cb0f6"}},h=k[f]||k.green,c={sm:{px:"16px",py:"8px",fontSize:"0.875rem"},md:{px:"24px",py:"12px",fontSize:"1rem"},lg:{px:"32px",py:"16px",fontSize:"1.125rem"}},E=c[m]||c.md,R=y=>{if(d||a)return;const M=y.currentTarget.getBoundingClientRect();W({x:y.clientX-M.left,y:y.clientY-M.top,show:!0}),setTimeout(()=>W({...j,show:!1}),500),A&&A(y)};return e.jsxs(p,{as:"button",className:`${he.button} ${v}`,onClick:R,disabled:d||a,style:{"--btn-bg":h.bg,"--btn-bg-hover":h.bgHover,"--btn-shadow":h.shadow,"--btn-text":h.text,"--btn-glow":h.glow,"--btn-border":h.border||"transparent","--btn-px":E.px,"--btn-py":E.py,"--btn-font-size":E.fontSize,width:N?"100%":"auto"},...F,children:[j.show&&e.jsx("span",{className:he.ripple,style:{left:j.x,top:j.y}}),e.jsx("span",{className:he.content,children:a?e.jsx(Pe,{size:"sm",color:h.text}):e.jsxs(e.Fragment,{children:[C&&e.jsx("span",{className:he.icon,children:C}),b,S&&e.jsx("span",{className:he.icon,children:S})]})})]})},ds="_container_15qty_3",hs="_cardWrapper_15qty_37",us="_skeleton_15qty_41",gs="_emptyState_15qty_73",ps="_emptyIcon_15qty_99",L={container:ds,cardWrapper:hs,skeleton:us,emptyState:gs,emptyIcon:ps};function Ns(){const[b,f]=r.useState([]),[m,N]=r.useState([]),[a,d]=r.useState(null),[A,C]=r.useState(!0),[S,v]=r.useState([]),[F,j]=r.useState(null),[W,k]=r.useState(null),{isOpen:h,onOpen:c,onClose:E}=xe(),{isOpen:R,onOpen:y,onClose:M}=xe(),{isOpen:te,onOpen:se,onClose:ne}=xe(),{isOpen:J,onOpen:ae,onClose:$}=xe(),i=Me(),[H,Z]=r.useState(0),[u,z]=r.useState([]),[Te,re]=r.useState([]),[oe,ie]=r.useState(1),[g,B]=r.useState(0),[Ie,mt]=r.useState(0),[ue,xt]=r.useState(""),[bt,Ve]=r.useState(!1),[D,Oe]=r.useState(null),[He,De]=r.useState(null),[Ke,Le]=r.useState([]),[Ue,qe]=r.useState(null),[$e,ze]=r.useState(null),[ge,Be]=r.useState(""),[ft,Ge]=r.useState(!1),{user:ce}=Ht(),Ne=Dt(),pe=st({base:"sm",md:"md"}),le=st({base:!1,md:!0})??!1,Ae=o("gray.50","gray.800");o("blue.50","blue.900"),o("blue.200","blue.700"),r.useEffect(()=>{G()},[]);const G=async()=>{C(!0),await Promise.all([me(),jt()]),C(!1)},jt=async()=>{try{const t=await I.getAll(),s=t.data?.data||t.data||[];N(Array.isArray(s)?s:[])}catch{}},me=async()=>{try{const t=await V.getAll();let s=t.data?.data||t.data||[];Array.isArray(s)||(s=s.data||s.items||[]);const n=Array.isArray(s)?s.map(l=>
1({...l,wordCount:l.wordCount||l.vocabularies?.length||0,learnedCount:l.learnedCount||0,createdAt:l.createdAt||new Date().toISOString()})):[];f(n)}catch(t){i({title:"Lỗi tải dữ liệu",description:t.response?.data?.message||"Không thể tải bộ từ vựng",status:"error",duration:4e3}),f([])}finally{C(!1)}},Qe=()=>{j(null),c()},yt=()=>{Be(""),ae()},Xe=async()=>{if(ge.trim())try{Ge(!0);const t=await I.create({name:ge.trim()}),s=t.data?.data||t.data;N(n=>[...n,s]),Be(""),$(),i({title:"Đã tạo thư mục mới",status:"success",duration:2e3})}catch(t){i({title:"Lỗi tạo thư mục",description:t.response?.data?.message||"Không thể tạo thư mục",status:"error",duration:3e3})}finally{Ge(!1)}},wt=t=>{j(t),c()},Ct=t=>{k(t),y()},St=async t=>{try{const n=(await V.getShareLink(t.id)).data;if(!n)throw new Error("Không nhận được dữ liệu từ server");if(n.statusCode&&n.statusCode!==200)throw new Error(n.message||"Không thể tạo link chia sẻ");const l=n.data||n;if(!l?.token)throw new Error("Server không trả về token chia sẻ");const Q=`${window.location.origin}/home?sharedCategory=${t.id}&sharedToken=${encodeURIComponent(l.token)}`;await navigator.clipboard.writeText(Q),i({title:"Đã sao chép link chia sẻ",description:"Link đã được sao chép. Chia sẻ với bạn bè nhé!",status:"success",duration:3e3})}catch(s){i({title:"Không thể sao chép",description:s.message||"Không thể sao chép",status:"error",duration:3e3})}},vt=async t=>{if(window.confirm("Bạn có chắc muốn xóa bộ từ này?"))try{await V.delete(t),f(b.filter(s=>s.id!==t)),v(s=>s.filter(n=>n!==t)),i({title:"Đã xóa bộ từ",status:"success",duration:2e3})}catch(s){i({title:"Lỗi xóa",description:s.response?.data?.message||"Không thể xóa bộ từ",status:"error",duration:4e3})}},Ft=async t=>{if(window.confirm(`Xóa bộ từ "${t.name}" khỏi thư mục?`))try{await V.update(t.id,{folderId:null}),i({title:"Đã xóa khỏi thư mục",status:"success",duration:2e3}),G()}catch{i({title:"Lỗi",description:"Không thể xóa khỏi thư mục",status:"error",duration:3e3})}},kt=t=>{Ne(`/practice?categoryId=${t.id}`)},Tt=(t,s)=>{t==="edit"&&wt(s),t==="delete"&&vt(s.id),t==="view"&&Ct(s),t==="learn"&&kt(s),t==="share"&&St(s),t==="removeFromFolder"&&Ft(s)},It=(t,s)=>{v(n=>s?[...n,t]:n.filter(l=>l!==t))},Lt=()=>{v([]),G()},zt=t=>{d(t),v([])},Bt=()=>{d(null),v([])},Nt=async(t,s)=>{if(t==="rename"){const n=window.prompt("Nhập tên mới cho thư mục:",s.name);if(!n||n.trim()===""||n.trim()===s.name)return;try{await I.update(s.id,{name:n.trim()}),i({title:"Đã đổi tên thư mục",status:"success",duration:2e3}),G(),a&&a.id===s.id&&d(l=>({...l,name:n.trim()}))}catch(l){i({title:"Lỗi đổi tên",description:l.response?.data?.message||"Không thể đổi tên",status:"error",duration:3e3})}}if(t==="delete"){if(!window.confirm("Bạn có chắc muốn xóa thư mục này? Các bộ từ bên trong sẽ được chuyển ra ngoài."))return;try{await I.delete(s.id),i({title:"Đã xóa thư mục",status:"success",duration:2e3}),G(),a&&a.id===s.id&&d(null)}catch(n){i({title:"Lỗi xóa thư mục",description:n.response?.data?.message||"Không thể xóa",status:"error",duration:3e3})}}if(t==="toggleShare")try{const n=!s.isShared;await I.update(s.id,{isShared:n}),i({title:n?"Đã chia sẻ thư mục công khai":"Đã hủy chia sẻ thư mục",status:"success",duration:2e3}),G()}catch(n){i({title:"Lỗi",description:n.response?.data?.message||"Không thể cập nhật chia sẻ",status:"error",duration:3e3})}},We=r.useCallback(async(t=1,s="")=>{Ve(!0);try{const[n,l]=await Promise.all([I.getTrending(),I.getNewest({page:t,limit:6,search:s||void 0})]),Q=n.data?.data||[],T=l.data||{};z(Q),re(T.data||[]),B(T.total||0),mt(T.totalPages||0),ie(T.page||t);const K=[...Q.map(de=>de.id),...(T.data||[]).map(de=>de.id)];if(ce&&K.length>0)try{const de=await I.getUserUpvotes(K);Le(de.data?.data||[])}catch{Le([])}}catch{z([]),re([])}finally{Ve(!1)}},[ce]);r.useEffect(()=>{H===1&&We(oe,ue)},[H]);const Ye=()=>{ie(1),We(1,ue)},At=t=>
1{ie(t),We(t,ue)},Je=async t=>{if(!ce){i({title:"Vui lòng đăng nhập để vote",status:"warning",duration:2e3});return}try{const s=await I.toggleUpvote(t.id),{upvoted:n,upvoteCount:l}=s.data?.data||{},Q=T=>T.map(K=>K.id===t.id?{...K,upvoteCount:l}:K);z(T=>Q(T)),re(T=>Q(T)),Le(T=>n?[...T,t.id]:T.filter(K=>K!==t.id))}catch{i({title:"Lỗi vote",status:"error",duration:2e3})}},Ze=async t=>{try{const s=await I.getSharedDetail(t.id),n=s.data?.data||s.data||{};Oe(n)}catch{i({title:"Lỗi",description:"Không thể tải chi tiết thư mục",status:"error",duration:3e3})}},Wt=t=>{De(t),y()},_t=t=>{if(!ce){i({title:"Vui lòng đăng nhập để sao chép",status:"warning",duration:2e3});return}qe(t)},Et=t=>{t?.wordLimitError?ze(t.wordLimitError):me()},Rt=async()=>{if(!ce){i({title:"Vui lòng đăng nhập để sao chép",status:"warning",duration:2e3});return}if(D)try{await I.copySharedFolder(D.id),i({title:"Đã sao chép toàn bộ thư mục",status:"success",duration:3e3}),G()}catch(t){t.response?.status===403?ze(t.response?.data?.message):i({title:"Lỗi sao chép thư mục",description:t.response?.data?.message||"Không thể sao chép",status:"error",duration:4e3})}},et=a?[]:m,tt=a?b.filter(t=>t.folderId===a.id):b.filter(t=>!t.folderId),Mt=async t=>{try{if(F){const s=await V.update(F.id,t),n=s.data?.data||s.data;f(b.map(l=>l.id===F.id?{...n,wordCount:n.vocabularies?.length||l.wordCount}:l)),i({title:"Đã cập nhật bộ từ",status:"success",duration:2e3})}else{const s=a?{...t,folderId:a.id}:t,n=await V.create(s),l=n.data?.data||n.data;f([...b,{...l,wordCount:0}]),i({title:"Đã tạo bộ từ mới",status:"success",duration:2e3})}E(),me()}catch(s){i({title:"Lỗi lưu",description:s.response?.data?.message||"Không thể lưu bộ từ",status:"error",duration:4e3})}};return e.jsxs(Zt,{maxW:"container.xl",py:6,className:L.container,children:[e.jsx(Kt,{title:"Bộ Từ Vựng Của Tôi - Luyện Từ | Quản Lý Từ Vựng Tiếng Anh Cá Nhân",description:"Tạo và quản lý bộ từ vựng tiếng Anh cá nhân. Sắp xếp từ vựng TOEIC, IELTS theo chủ đề, thư mục để học hiệu quả hơn với Flashcard và Spaced Repetition.",keywords:"bộ từ vựng, quản lý từ vựng, học tiếng Anh, flashcard cá nhân, từ vựng TOEIC, từ vựng IELTS",path:"/category-list",noindex:!0}),e.jsxs(es,{index:H,onChange:Z,variant:"soft-rounded",colorScheme:"purple",children:[e.jsxs(Y,{justify:"space-between",align:"center",mb:4,flexWrap:"wrap",gap:3,children:[e.jsxs(O,{spacing:2,flexWrap:{base:"wrap",md:"nowrap"},children:[e.jsx(P,{variant:"green",size:pe,onClick:Qe,leftIcon:le?e.jsx(Ee,{}):null,children:"Tạo bộ từ"}),e.jsx(P,{variant:"blue",size:pe,onClick:yt,leftIcon:le?e.jsx(nt,{}):null,children:"Tạo folder"}),e.jsx(P,{variant:"yellow",size:pe,onClick:()=>Ne("/roadmap"),leftIcon:le?e.jsx(Ut,{}):null,children:"Lộ trình"}),S.length>0&&e.jsxs(P,{variant:"blue",onClick:se,leftIcon:le?e.jsx(nt,{}):null,children:["Thêm vào thư mục (",S.length,")"]})]}),e.jsxs(O,{spacing:2,flexWrap:"wrap",justify:"flex-end",children:[e.jsxs(ts,{gap:2,children:[e.jsxs(ht,{children:[e.jsx(x,{as:U,mr:2})," Bộ từ của tôi"]}),e.jsxs(ht,{children:[e.jsx(x,{as:at,mr:2})," Cộng đồng"]})]}),e.jsx(_,{leftIcon:le?e.jsx(rt,{}):void 0,borderRadius:"full",colorScheme:"teal",variant:"outline",size:pe,onClick:()=>Ne("/classes"),children:"Lớp học"})]})]}),e.jsxs(ss,{children:[e.jsx(ut,{p:0,children:e.jsxs(q,{spacing:6,align:"stretch",children:[a&&e.jsxs(Y,{align:"center",mb:2,children:[e.jsx(P,{variant:"ghost",onClick:Bt,leftIcon:e.jsx(ot,{}),size:"sm",children:"Quay lại"}),e.jsx(x,{as:it,mx:2,color:"gray.400"}),e.jsx(x,{as:U,mr:2,color:"blue.500"}),e.jsx(ee,{size:"md",color:"gray.700",children:a.name})]}),A?e.jsx(X,{columns:{base:1,sm:2,md:3,lg:5},spacing:4,children:[1,2,3,4,5,6].map(t=>e.jsx(p,{className:L.skeleton,height:"180px",borderRadius:"xl"},t))}):et.length===0&&tt.length===0?e.jsxs(p,{className:L.emptyState,bg:Ae,children:[e.jsx(p,{className:L.emptyIcon,children:e.jsx(x,{as:U,boxSize:16,color:"gray.300"})}),e.jsx(ee,{size:"md",color:"gray.500",mb:2,children:a?"Thư mục trống":"Chưa có bộ từ nào"}),e.jsx(w,{color:"gray.400",mb:6,maxW:"300px",children:a?"Thêm bộ từ vào thư mục này để bắt đầu học":"Bắt đầu bằng cách tạo bộ từ vựng đầu tiên của bạn"}),!a&&e.jsx(P,{variant:"green",onClick:Qe,leftIcon:e.jsx(Ee,{}),children:"Tạo bộ từ"})]}):e.jsxs(X,{columns:{base:1,sm:2,md:3,lg:5},spacing:4,children:[et.map(t=>{const s=b.filter(n=>n.folderId===t.id);return e.jsx(p,{className:L.cardWrapper,children:e.jsx(_e,{folder:t,onClick:zt,onAction:Nt,itemCount:s.length})},`folder-${t.id}`)}),tt.map(t=>e.jsx(p,{className:L.cardWrapper,children:e.jsx(lt,{category:t,onAction:Tt,isPublic:!1,isSelected:S.includes(t.id),onSelect:It,isInFolder:!!a})},t.id))]})]})}),e.jsx(ut,{p:0,children:e.jsx(q,{spacing:6,align:"stretch",children:D?e.jsxs(q,{spacing:4,align:"stretch",children:[e.jsxs(Y,{direction:{base:"column",md:"row"},align:{base:"stretch",md:"center"},gap:{base:3,md:2},mb:2,children:[e.jsxs(Y,{direction:{base:"column",sm:"row"},align:{base:"stretch",sm:"center"},gap:{base:2,sm:2},minW:0,flex:"1",children:[e.jsx(P,{variant:"ghost",onClick:()=>Oe(null),leftIcon:e.jsx(ot,{}),size:"sm",alignSelf:{base:"flex-start",sm:"center"},flexShrink:0,children:"Quay lại"}),e.jsx(x,{as:it,color:"gray.400",display:{base:"none",md:"block"},flexShrink:0}),e.jsxs(Y,{align:"center",gap:2,minW:0,flex:"1",flexWrap:"wrap",children:[e.jsx(x,{as:U,color:"orange.500",flexShrink:0}),e.jsx(ee,{size:"md",minW:0,lineHeight:"shorter",wordBreak:"break-word",children:D.name}
1),D.user&&e.jsxs(qt,{colorScheme:"blue",fontSize:"sm",display:"inline-flex",alignItems:"center",gap:1,maxW:{base:"100%",sm:"220px"},children:[e.jsx(x,{as:rt,boxSize:3,flexShrink:0}),e.jsx(w,{as:"span",noOfLines:1,children:D.user.name})]})]})]}),e.jsx(P,{variant:"blue",size:"sm",alignSelf:{base:"stretch",md:"center"},flexShrink:0,leftIcon:e.jsx(Re,{}),onClick:Rt,children:"Sao chép folder"})]}),D.categories?.length===0?e.jsx(p,{className:L.emptyState,bg:Ae,children:e.jsx(w,{color:"gray.500",children:"Thư mục này chưa có bộ từ nào"})}):e.jsx(X,{columns:{base:1,sm:2,md:3,lg:5},spacing:4,children:D.categories?.map(t=>e.jsx(p,{className:L.cardWrapper,children:e.jsx(lt,{category:t,onAction:(s,n)=>{s==="view"&&Wt(n),s==="copy"&&_t(n)},isPublic:!0})},t.id))})]}):e.jsxs(e.Fragment,{children:[e.jsxs(Y,{gap:3,flexWrap:"wrap",align:"center",children:[e.jsxs(gt,{maxW:"400px",children:[e.jsx(pt,{pointerEvents:"none",children:e.jsx(x,{as:ct,color:"gray.400"})}),e.jsx(je,{placeholder:"Tìm kiếm thư mục...",value:ue,onChange:t=>xt(t.target.value),onKeyDown:t=>t.key==="Enter"&&Ye(),borderRadius:"xl"})]}),e.jsx(P,{variant:"blue",onClick:Ye,leftIcon:e.jsx(ct,{}),children:"Tìm kiếm"})]}),bt?e.jsx(X,{columns:{base:1,sm:2,md:3},spacing:4,children:[1,2,3].map(t=>e.jsx(p,{className:L.skeleton,height:"180px",borderRadius:"xl"},t))}):e.jsxs(e.Fragment,{children:[u.length>0&&e.jsxs(p,{children:[e.jsxs(O,{mb:3,children:[e.jsx(x,{as:$t,color:"red.500"}),e.jsx(ee,{size:"sm",color:"red.500",children:"Thịnh hành"})]}),e.jsx(X,{columns:{base:1,sm:2,md:3},spacing:4,children:u.map(t=>e.jsx(p,{className:L.cardWrapper,children:e.jsx(_e,{folder:t,onClick:Ze,itemCount:t.categoryCount||0,isPublicView:!0,isUpvoted:Ke.includes(t.id),onUpvote:Je})},`trend-${t.id}`))})]}),(()=>{const t=new Set(u.map(n=>n.id)),s=Te.filter(n=>!t.has(n.id));return e.jsxs(p,{children:[e.jsxs(O,{mb:3,children:[e.jsx(x,{as:U,color:"blue.500"}),e.jsx(ee,{size:"sm",color:"blue.500",children:"Mới nhất"})]}),s.length===0?e.jsxs(p,{className:L.emptyState,bg:Ae,children:[e.jsx(p,{className:L.emptyIcon,children:e.jsx(x,{as:at,boxSize:16,color:"gray.300"})}),e.jsx(ee,{size:"md",color:"gray.500",mb:2,children:"Chưa có thư mục nào được chia sẻ"}),e.jsx(w,{color:"gray.400",maxW:"300px",children:"Hãy chia sẻ thư mục từ vựng của bạn để mọi người cùng học nhé!"})]}):e.jsx(X,{columns:{base:1,sm:2,md:3},spacing:4,children:s.map(n=>e.jsx(p,{className:L.cardWrapper,children:e.jsx(_e,{folder:n,onClick:Ze,itemCount:n.categoryCount||0,isPublicView:!0,isUpvoted:Ke.includes(n.id),onUpvote:Je})},`new-${n.id}`))}),e.jsx(Yt,{currentPage:oe,totalPages:Ie,totalItems:g,onPageChange:At,itemsName:"thư mục"})]})})()]})]})})})]})]}),e.jsx(ns,{isOpen:h,onClose:E,category:F,onSave:Mt}),e.jsx(Qt,{isOpen:R,onClose:()=>{M(),De(null)},category:He||W,isPublic:!!He,onWordUpdated:me}),e.jsx(as,{isOpen:te,onClose:ne,selectedCategoryIds:S,onSuccess:Lt}),e.jsx(rs,{isOpen:!!Ue,onClose:()=>qe(null),category:Ue,onSuccess:Et}),e.jsx(Jt,{isOpen:!!$e,onClose:()=>ze(null),message:$e}),e.jsxs(ye,{isOpen:J,onClose:$,isCentered:!0,size:"md",children:[e.jsx(we,{backdropFilter:"blur(4px)"}),e.jsxs(Ce,{borderRadius:"xl",children:[e.jsx(Se,{children:"Tạo folder mới"}),e.jsx(ve,{}),e.jsx(Fe,{children:e.jsxs(q,{spacing:4,align:"stretch",children:[e.jsx(w,{color:"gray.500",fontSize:"sm",children:"Tạo thư mục để gom các bộ từ cùng chủ đề vào một chỗ."}),e.jsxs(be,{isRequired:!0,children:[e.jsx(fe,{children:"Tên folder"}),e.jsx(je,{value:ge,onChange:t=>Be(t.target.value),onKeyDown:t=>{t.key==="Enter"&&(t.preventDefault(),Xe())},placeholder:"Ví dụ: IELTS Writing",autoFocus:!0})]})]})}),e.jsxs(ke,{children:[e.jsx(_,{variant:"ghost",mr:3,onClick:$,children:"Hủy"}),e.jsx(_,{colorScheme:"blue",onClick:Xe,isLoading:ft,isDisabled:!ge.trim(),children:"Tạo folder"})]})]})]})]})}export{Ns as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.