PageSourceSearch

https://sellcademy.co.kr/assets/AdminUserListPage-bd16NINM.js

js sellcademy.co.kr collected 2026-09-24 15:05:14 UTC 14,358 bytes, 1 lines download raw bytes

1import{c as oe,j as e,C as le,m as ce,B as M,r as c,b as V,t as v,u as de,K as ue,T as me,a2 as xe}from"./index-CnD64O-O.js";import{g as he,a as pe,u as ge,d as be}from"./admin-NtP17WyB.js";import{P as fe}from"./Pagination-BZdcQiyp.js";import{S as W}from"./switch-B87kDLN-.js";import{I as E}from"./input-C48x21mA.js";import{L as F}from"./label-BrNY7LbK.js";import{S as O,a as X,b as q,c as G,d as m}from"./select-DM4MWNIY.js";import{S as Q}from"./search-Dc68Zg49.js";import{R as ee}from"./rotate-ccw-DmaXJd3Q.js";import{u as je,A as ve,f as Se,g as Ne}from"./AdminUserTanStackTableHeader-DrYFIm8f.js";import{B as L}from"./badge-CYge-pgM.js";import{T as Ce,a as ye,b as J,d as ke,e as D}from"./table-BmB_chFW.js";import{S as we}from"./SubscriptionStatusBadge-CApL5MIM.js";import{S as Te}from"./shield-check-jI1FfI4B.js";import{C as Ae}from"./copy-CPr4GYhI.js";import{A as Fe}from"./AdminPageHeader-07uqLHgw.js";import{U as Y}from"./users-CkG7qrFU.js";import{C as Je}from"./credit-card-BSPaBLtw.js";import{D as Pe}from"./download-CLDSaj8z.js";import"./chevron-left-DyzQWZgR.js";import"./chevron-right-92kdo-2C.js";import"./index-QtH-xY58.js";import"./chevron-down-CjwehzcN.js";import"./check-CSNy1TZ9.js";import"./chevron-up-Cgk6_S1X.js";import"./index-BdQq_4o_.js";import"./index-DxCoXAjk.js";import"./index-CW7ZL7oC.js";import"./index-D6trnHb-.js";const Ue=[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["line",{x1:"17",x2:"22",y1:"8",y2:"13",key:"3nzzx3"}],["line",{x1:"22",x2:"17",y1:"8",y2:"13",key:"1swrse"}]],Re=oe("user-x",Ue),I="all",_="all";function Ee({searchInput:o,onSearchInputChange:g,onSearchSubmit:x,statusFilter:l,onStatusFilterChange:h,subFilter:d,onSubFilterChange:S,dateJoinedFrom:N,onDateJoinedFromChange:C,dateJoinedTo:b,onDateJoinedToChange:f,onReset:u}){return e.jsx(le,{className:"bg-muted/30",children:e.jsxs(ce,{className:"flex flex-col gap-5",children:[e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx(F,{className:"text-label",children:"검색"}),e.jsxs("div",{className:"relative w-full",children:[e.jsx(Q,{className:"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"}),e.jsx(E,{placeholder:"이름, 이메일, 전화번호를 입력하세요",value:o,onChange:n=>g(n.target.value),onKeyDown:n=>n.key==="Enter"&&x(),className:"pl-9 bg-background"})]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3 sm:grid-cols-4",children:[e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx(F,{className:"text-label",children:"계정 상태"}),e.jsxs(O,{value:l||I,onValueChange:n=>h(n===I?"":n),children:[e.jsx(X,{className:"w-full bg-background",children:e.jsx(q,{})}),e.jsxs(G,{children:[e.jsx(m,{value:I,children:"전체"}),e.jsx(m,{value:"active",children:"활성"}),e.jsx(m,{value:"inactive",children:"비활성"})]})]})]}),e.jsxs("div",{className:"flex flex-col gap-1.5",children:[e.jsx(F,{className:"text-label",children:"구독"}),e.jsxs(O,{value:d||_,onValueChange:n=>S(n===_?"":n),children:[e.jsx(X,{className:"w-full bg-background",children:e.jsx(q,{})}),e.jsxs(G,{children:[e.jsx(m,{value:_,children:"전체"}),e.jsx(m,{value:"active",children:"구독 중"}),e.jsx(m,{value:"payment_issue",children:"결제 문제"}),e.jsx(m,{value:"cancelled",children:"구독 취소"}),e.jsx(m,{value:"refunded",children:"환불 해지"}),e.jsx(m,{value:"expired",children:"구독 만료"}),e.jsx(m,{value:"none",children:"미구독"})]})]})]}),e.jsxs("div",{className:"col-span-2 flex flex-col gap-1.5",children:[e.jsx(F,{className:"text-label",children:"가입일"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(E,{type:"date",value:N,onChange:n=>C(n.target.value),className:"w-full bg-background"}),e.jsx("span",{className:"text-body-sm text-muted-foreground",children:"~"}),e.jsx(E,{type:"date",value:b,onChange:n=>f(n.target.value),className:"w-full bg-background"})]})]})]}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsxs(M,{variant:"outline",onClick:u,children:[e.jsx(ee,{className:"mr-1 h-4 w-4"}),"초기화"]}),e.jsxs(M,{onClick:x,children:[e.jsx(Q,{className:"mr-1 h-4 w-4"}),"검색"]})]})]})})}const Z=new Set(["index","role","subscriptionPlan","subscriptionStatus","identityVerified","isActive"]);function Le({users:o,loading:g,page:x,pageSize:l,sortType:h,sortOrder:d,onSortChange:S,phoneMasked:N,onToggleActive:C,onRowClick:b}){const f=c.useMemo(()=>[{id:"index",header:"연번",enableSorting:!1,cell:({row:s})=>(x-1)*l+s.index+1},{id:"email",header:"이메일",accessorFn:s=>s.email,enableSorting:!0,cell:({row:s})=>e.jsx("span",{className:"text-body-sm",children:s.original.email})},{id:"name",header:"이름",accessorFn:s=>s.name,enableSorting:!0,cell:({row:s})=>
1{const t=s.original.name||"—",i=s.original.identity?.name,j=i&&i!==s.original.name;return e.jsx("span",{className:"text-body-sm",children:j?`${t}(${i})`:t})}},{id:"role",header:"권한",accessorFn:s=>s.isStaff?1:0,enableSorting:!0,cell:({row:s})=>s.original.isStaff?e.jsxs(L,{className:"border-amber-300 bg-amber-50 text-amber-700 hover:bg-amber-50",children:[e.jsx(Te,{className:"mr-1 h-3 w-3"}),"관리자"]}):e.jsx("span",{className:"text-caption text-muted-foreground",children:"일반"})},{id:"subscriptionPlan",header:"구독 플랜",accessorFn:s=>s.subscription?.plan.name??"",enableSorting:!0,cell:({row:s})=>{const t=s.original.subscription;return t?e.jsx(L,{variant:"outline",className:"border-blue-300 text-blue-600",children:t.plan.name}):e.jsx("span",{className:"text-caption text-muted-foreground",children:"—"})}},{id:"subscriptionStatus",header:"구독 상태",accessorFn:s=>s.subscription?.status??"none",enableSorting:!0,cell:({row:s})=>{const t=s.original.subscription?.status??"none";return e.jsx(we,{status:t})}},{id:"subscriptionExpiresAt",header:"구독 만료일",accessorFn:s=>s.subscription?.expiresAt??"",enableSorting:!0,cell:({row:s})=>e.jsx("span",{className:"text-caption text-muted-foreground",children:s.original.subscription?new Date(s.original.subscription.expiresAt).toLocaleDateString("ko-KR"):"—"})},{id:"dateJoined",header:"가입일",accessorFn:s=>s.dateJoined,enableSorting:!0,cell:({row:s})=>e.jsx("span",{className:"text-caption text-muted-foreground",children:new Date(s.original.dateJoined).toLocaleDateString("ko-KR")})},{id:"identityVerified",header:"본인인증",accessorFn:s=>s.identity?.verifiedAt??"",enableSorting:!0,cell:({row:s})=>s.original.identity?e.jsx(L,{className:"border-green-300 bg-green-50 text-green-700 hover:bg-green-50",children:"완료"}):e.jsx("span",{className:"text-caption text-muted-foreground",children:"미인증"})},{id:"phone",header:"휴대폰",accessorFn:s=>s.identity?.phone??"",enableSorting:!0,cell:({row:s})=>{const t=s.original.identity;if(!t)return e.jsx("span",{className:"text-caption text-muted-foreground",children:"—"});const i=j=>{j.stopPropagation(),navigator.clipboard.writeText(t.phone),v.success("복사되었습니다.")};return e.jsxs("div",{className:"flex items-center gap-1",onClick:j=>j.stopPropagation(),children:[e.jsx("span",{className:"text-caption text-muted-foreground",children:N?t.phone.replace(/(\d{3})(\d{4})(\d{4})/,"$1-****-$3"):t.phone.replace(/(\d{3})(\d{4})(\d{4})/,"$1-$2-$3")}),e.jsx("button",{type:"button",className:"text-muted-foreground hover:text-foreground transition-colors",onClick:i,children:e.jsx(Ae,{className:"h-3 w-3"})})]})}},{id:"isActive",header:"계정 활성화",enableSorting:!1,cell:({row:s})=>e.jsx("div",{className:"flex justify-center",onClick:t=>t.stopPropagation(),children:e.jsx(W,{checked:s.original.isActive,onCheckedChange:()=>C(s.original.id,s.original.isActive),"aria-label":"계정 활성화"})})}],[x,l,N,C]),u=h?[{id:h,desc:d==="desc"}]:[],p=je({data:o,columns:f,state:{sorting:u},onSortingChange:s=>{const t=typeof s=="function"?s(u):s;if(t.length===0){S(null,"asc");return}const i=t[0];S(i.id,i.desc?"desc":"asc")},getCoreRowModel:Ne(),manualSorting:!0});return e.jsx("div",{className:"rounded-lg border",children:e.jsxs(Ce,{children:[e.jsx(ye,{className:"bg-muted/50",children:p.getHeaderGroups().map(s=>e.jsx(J,{children:s.headers.map(t=>{const i=Z.has(t.column.id);return e.jsx(ve,{header:t,align:i?"center":"left",className:V(t.column.id==="index"&&"w-[50px]",i&&"text-center")},t.id)})},s.id))}),e.jsx(ke,{children:g?e.jsx(J,{children:e.jsx(D,{colSpan:f.length,className:"h-32 text-center text-muted-foreground",children:"불러오는 중..."})}):o.length===0?e.jsx(J,{children:e.jsx(D,{colSpan:f.length,className:"h-32 text-center text-muted-foreground",children:"사용자가 없습니다."})}):p.getRowModel().rows.map(s=>e.jsx(J,{className:"cursor-pointer hover:bg-accent/50",onClick:()=>b(s.original.id),children:s.getVisibleCells().map(t=>{const i=Z.has(t.column.id);return e.jsx(D,{className:V(t.column.id==="index"&&"text-center font-mono text-caption",i&&t.column.id!=="index"&&"text-center"),children:Se(t.column.columnDef.cell,t.getContext())},t.id)})},s.id))})]})})}function k({icon:o,label:g,value:x,onClick:l}){return e.jsxs("button",{type:"button",onClick:l,className:V("rounded-lg border bg-card p-4 text-left transition-colors",l&&"cursor-pointer hover:bg-accent/50"),children:[e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground",children:[o,e.jsx("span",{className:"text-body-sm",children:g})]}),e.jsx("p",{className:"mt-2 text-h3 tabular-nums",children:x.toLocaleStr
1ing()})]})}const T=20,De=["email","name","role","subscriptionPlan","subscriptionStatus","subscriptionExpiresAt","dateJoined","identityVerified","phone"],Ie=o=>o&&De.includes(o)?o:null,_e=o=>o==="desc"?"desc":"asc",A=()=>({search:"",status:"",subscription:"",dateJoinedFrom:"",dateJoinedTo:""});function hs(){const o=de(),[g,x]=ue(),l=Ie(g.get("type")),h=_e(g.get("sort")),[d,S]=c.useState(null),[N,C]=c.useState([]),[b,f]=c.useState(0),[u,n]=c.useState(1),[p,s]=c.useState(A),[t,i]=c.useState(A),[j,B]=c.useState(!1),[$,se]=c.useState(!0),[H,z]=c.useState(!1),P=c.useCallback(()=>{he().then(S).catch(()=>v.error("통계를 불러오지 못했습니다."))},[]),U=c.useCallback(()=>{B(!0),pe({page:u,pageSize:T,search:t.search||void 0,dateJoinedFrom:t.dateJoinedFrom||void 0,dateJoinedTo:t.dateJoinedTo||void 0,status:t.status||void 0,subscription:t.subscription||void 0,type:l??void 0,sort:l?h:void 0}).then(a=>{C(a.results),f(a.count)}).catch(()=>v.error("사용자 목록을 불러오지 못했습니다.")).finally(()=>B(!1))},[u,t,l,h]),te=(a,r)=>{n(1),x(R=>{const w=new URLSearchParams(R);return a===null?(w.delete("type"),w.delete("sort")):(w.set("type",a),w.set("sort",r)),w},{replace:!0})};c.useEffect(()=>{P()},[P]),c.useEffect(()=>{U()},[U]);const ae=()=>{n(1),i(p)},ne=()=>{s(A()),i(A()),n(1)},y=a=>{const r={...A(),...a};s(r),i(r),n(1)},ie=async(a,r)=>{try{const R=await ge(a,{isActive:!r});U(),P(),v.success(R.isActive?"계정을 활성화했습니다.":"계정을 비활성화했습니다.")}catch{v.error("계정 상태 변경에 실패했습니다.")}},re=async()=>{z(!0);try{await be({search:t.search||void 0,dateJoinedFrom:t.dateJoinedFrom||void 0,dateJoinedTo:t.dateJoinedTo||void 0,status:t.status||void 0,subscription:t.subscription||void 0,type:l??void 0,sort:l?h:void 0}),v.success("사용자 목록을 다운로드했습니다.")}catch{v.error("사용자 목록 다운로드에 실패했습니다.")}finally{z(!1)}},K=Math.ceil(b/T);return e.jsxs("div",{children:[e.jsx(Fe,{title:"사용자 관리",description:"전체 사용자와 구독 상태를 검색·관리합니다."}),d&&e.jsxs("div",{className:"mt-6 flex flex-col gap-2",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-6",children:[e.jsx(k,{icon:e.jsx(Y,{className:"h-5 w-5"}),label:"전체 사용자",value:d.totalUsers,onClick:()=>y({})}),e.jsx(k,{icon:e.jsx(Y,{className:"h-5 w-5 text-green-600"}),label:"활성 사용자",value:d.activeUsers,onClick:()=>y({status:"active"})}),e.jsx(k,{icon:e.jsx(Je,{className:"h-5 w-5 text-blue-600"}),label:"구독 중",value:d.activeSubscriptions,onClick:()=>y({subscription:"active"})}),e.jsx(k,{icon:e.jsx(me,{className:"h-5 w-5 text-amber-500"}),label:"결제 문제",value:d.paymentIssueSubscriptions,onClick:()=>y({subscription:"payment_issue"})}),e.jsx(k,{icon:e.jsx(Re,{className:"h-5 w-5 text-red-500"}),label:"구독 취소",value:d.cancelledSubscriptions,onClick:()=>y({subscription:"cancelled"})}),e.jsx(k,{icon:e.jsx(ee,{className:"h-5 w-5 text-orange-500"}),label:"환불 해지",value:d.refundedSubscriptions,onClick:()=>y({subscription:"refunded"})})]}),e.jsx("p",{className:"text-caption text-muted-foreground",children:"사용자 수를 세는 앞의 두 장을 빼면 나머지는 구독 건수 기준입니다 — 한 사용자가 구독을 여러 건 가질 수 있어 카드를 눌렀을 때 나오는 사용자 수와 다를 수 있습니다. '결제 문제'는 결제 재시도 중·결제 실패·결제카드 등록 필요를 합친 값입니다."})]}),e.jsx("div",{className:"mt-8",children:e.jsx(Ee,{searchInput:p.search,onSearchInputChange:a=>s(r=>({...r,search:a})),onSearchSubmit:ae,statusFilter:p.status,onStatusFilterChange:a=>s(r=>({...r,status:a})),subFilter:p.subscription,onSubFilterChange:a=>s(r=>({...r,subscription:a})),dateJoinedFrom:p.dateJoinedFrom,onDateJoinedFromChange:a=>s(r=>({...r,dateJoinedFrom:a})),dateJoinedTo:p.dateJoinedTo,onDateJoinedToChange:a=>s(r=>({...r,dateJoinedTo:a})),onReset:ne})}),e.jsxs("div",{className:"mt-8 flex items-center justify-end gap-4",children:[e.jsxs("label",{className:"flex items-center gap-2 text-caption text-muted-foreground",children:["휴대폰 번호 마스킹",e.jsx(W,{checked:$,onCheckedChange:se,"aria-label":"휴대폰 번호 마스킹"})]}),e.jsxs(M,{variant:"outline",size:"sm",onClick:re,disabled:H,children:[e.jsx(Pe,{className:"mr-1 h-4 w-4"}
1),H?"다운로드 중...":"검색 결과 다운로드"]})]}),e.jsx("div",{className:"mt-2",children:e.jsx(Le,{users:N,loading:j,page:u,pageSize:T,sortType:l,sortOrder:h,onSortChange:te,phoneMasked:$,onToggleActive:ie,onRowClick:a=>o(xe(a))})}),K>1&&e.jsxs("div",{className:"mt-4 flex items-center justify-between",children:[e.jsxs("p",{className:"text-body-sm text-muted-foreground",children:["총 ",b,"명 중 ",(u-1)*T+1,"–",Math.min(u*T,b)]}),e.jsx(fe,{page:u,totalPages:K,onPageChange:n})]})]})}export{hs 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.