PageSourceSearch

https://kumachan-reservation.vercel.app/assets/AdminStaffPage-BWMlK0c_.js

js kumachan-reservation.vercel.app collected 2026-10-03 07:12:31 UTC 10,553 bytes, 1 lines download raw bytes

1import{l as R,b as L,f as D,j as e,L as O,m as B}from"./index-CM7l7STU.js";import{a as l}from"./vendor-sentry-BvJwuEUj.js";import{r as H}from"./admin-shop-dqytQ_3I.js";import{B as U,n as C}from"./slotAvailability-COATv3zD.js";import{C as $}from"./chevron-left-Cp3plKIY.js";import{P as q}from"./plus-CTKIi3ui.js";import{P as K}from"./pencil-BFQvlxyB.js";import{T as X}from"./trash-2-CYKnOBoN.js";import{X as J}from"./x-DWOAS2eT.js";import{b as Q}from"./vendor-react-D4FiQ0sB.js";import"./vendor-line-BRFMun8e.js";const V="/api/admin/staff";function p(n){return R(V,n,"スタッフ操作に失敗しました")}async function Y(n){const{id:o}=await p({action:"create",staff:n});return o}async function ee(n,o){await p({action:"update",id:n,staff:o})}async function te(n){await p({action:"delete",id:n})}async function se(n,o){await p({action:"toggle",id:n,is_active:o})}const W={name:"",display_name:"",line_user_id:"",role:"",is_active:!0,booking_cutoff:""},u={borderRadius:"12px",background:"var(--cream)",border:"1.5px solid var(--cream-3)",fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:300,color:"var(--ink)"},x={fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:300,fontSize:"12px",color:"var(--muted)"};function xe(){const n=L(),o=Q(),v=D(),[b,j]=l.useState([]),[c,z]=l.useState(null),[G,E]=l.useState(!0),[M,d]=l.useState(!1),[i,_]=l.useState(null),[a,f]=l.useState(W),[k,h]=l.useState(!1),[g,N]=l.useState(!1),[S,y]=l.useState(null),[w,r]=l.useState(null),m=async t=>{try{const s=await B(`/api/admin/staff?shop_id=${encodeURIComponent(t)}`);if(!s.ok)throw new Error(`HTTP ${s.status}`);const{staff:T}=await s.json();j(T??[])}catch(s){console.error("[AdminStaffPage] fetch error:",s),j([])}};l.useEffect(()=>{(async()=>{try{const t=await H();z(t.id),await m(t.id)}catch(t){console.error("[AdminStaffPage] load:",t),r("店舗情報の読み込みに失敗しました")}finally{E(!1)}})()},[]);const F=()=>{_(null),f(W),r(null),d(!0)},Z=t=>{_(t),f({name:t.name,display_name:t.display_name??"",line_user_id:t.line_user_id??"",role:t.role??"",is_active:t.is_active,booking_cutoff:String(C(t.booking_cutoff_minutes)??"")}),r(null),d(!0)},I=async()=>{if(!i&&!a.name.trim())return;if(!c){r("店舗情報が取得できていません");return}h(!0),r(null);const t={display_name:a.display_name.trim()||null,line_user_id:a.line_user_id.trim()||null,role:a.role.trim()||null,is_active:a.is_active,booking_cutoff_minutes:C(Number(a.booking_cutoff))};try{i?await ee(i.id,t):await Y({...t,shop_id:c,name:a.name.trim()})}catch(s){r(s instanceof Error?s.message:String(s)),h(!1);return}h(!1),d(!1),await m(c),v.success(i?"保存しました":"追加しました")},A=async t=>{if(c&&!g){N(!0);try{await te(t)}catch(s){r(s instanceof Error?s.message:String(s));return}finally{N(!1)}y(null),v.success("削除しました"),await m(c)}},P=async t=>{if(c){try{await se(t.id,!t.is_active)}catch(s){r(s instanceof Error?s.message:String(s));return}await m(c)}};return G?e.jsx(O,{}):e.jsxs("div",{className:n,style:{background:"var(--cream)",minHeight:"100dvh"},children:[e.jsxs("div",{className:"flex items-center gap-3 px-6 pt-4 pb-3",style:{borderBottom:"0.5px solid var(--cream-3)"},children:[e.jsx("button",{onClick:()=>o("/admin/setup"),style:{color:"var(--muted)"},children:e.jsx($,{size:22})}),e.jsx("h1",{className:"flex-1",style:{fontFamily:"'Sora', sans-serif",fontSize:"20px",fontWeight:300,color:"var(--ink)"},children:"スタッフ管理"}),e.jsxs("button",{onClick:F,className:"flex items-center gap-1.5 px-3 py-2 rounded-xl text-xs",style:{fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:400,background:"var(--ink-2)",color:"#fdfaf5",border:"0.5px solid rgba(47,158,143,0.3)"},children:[e.jsx(q,{size:14})," 追加"]})]}),e.jsx("div",{className:"px-6 py-4 flex flex-col gap-2.5",children:b.length===0?e.jsxs("div",{className:"p-8 text-center",style:{background:"var(--lux-white)",borderRadius:"18px",border:"0.5px solid var(--cream-3)"},children:[e.jsx("p",{style:{fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:300,fontSize:"13px",color:"var(--muted)"},children:"スタッフが登録されていません"}),e.jsx("button",{onClick:F,className:"mt-3 text-xs",style:{fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:300,color:"var(--gold-3)"},children:"+ 最初のスタッフを追加"})]}):b.map(t=>e.jsxs("div",{className:"flex items-start gap-3 p-4",style:{background:"var(--lux-white)",borderRadius:"18px",border:"0.5px solid var(--cream-3)"},children:[e.jsx("div",{className:"w-10 h-10 rounded-full flex items-center justify-center text-sm flex-shrink-0",style:{background:"var(--cream-2)",border:"0.5px solid var(--cream-3)",fontFamily:"'Sora', sans-serif",fontWeight:400,color:"var(--gold-3)"},children:t.name[0]}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("span",{style:{fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:300,fontSize:"14px",color:"var(--ink)"},children:t.name}),t.role&&e.jsx("span",{style:{fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:300,fontSize:"11px",color:"var(--muted)"},children:t.role}),e.jsx("span",{className:"text-[10px] px-2 py-0.5 rounded-full",style:{fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:300,background:t.is_active?"rgba(47,158,143,0.12)":"var(--cream-2)",color:t.is_active?"var(--gold-3)":"var(--muted)",border:`0.5px solid ${t.is_active?"rgba(47,158,143,0.3)":"var(--cream-3)"}`},children:t.is_active?"稼働中":"非稼働"})]}),t.line_user_id&&e.jsxs("p",{className:"text-xs mt-0.5 truncate",style:{fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:300,color:"var(--muted)"},children:["LINE ID: ",t.line_user_id]})]}),e.jsxs("div",{className:"flex items-center gap-1 flex-shrink-0",children:[e.jsx("button",{onClick:()=>P(t),className:"text-xs px-2 py-1 rounded-lg",style:{fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:300,color:"var(--muted)",border:"0.5px solid var(--cream-3)"},children:t.is_active?"非稼働に":"稼働に"}),e.jsx("button",{onClick:()=>Z(t),className:"p-2",style:{color:"var(--muted-2)"},children:e.jsx(K,{size:14})}),e.jsx("button",{onClick:()=>y(t.id),className:"p-2",style:{color:"var(--muted-2)"},children:e.jsx(X,{size:14})})]})]},t.id))}),M&&e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-end justify-center",children:e.jsxs("div",{className:"w-full max-w-[430px] rounded-t-3xl p-6 flex flex-col gap-4",style:{background:"var(--lux-white)"},children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("p",{style:{fontFamily:"'Sora', sans-serif",fontSize:"18px",fontWeight:300,color:"var(--ink)"},children:i?"スタッフを編集":"スタッフを追加"}),e.jsx("button",{onClick:()=>d(!1),style:{color:"var(--muted)"},children:e.jsx(J,{size:18})})]}),e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{style:x,children:i?"お客様に表示される名前"
1:e.jsxs(e.Fragment,{children:["名前 ",e.jsx("span",{className:"text-red-500",children:"*"})]})}),e.jsx("input",{className:"w-full px-6 py-3 text-sm focus:outline-none",style:u,placeholder:i?i.name:"例:山田 花子",value:i?a.display_name:a.name,onChange:t=>f(s=>i?{...s,display_name:t.target.value}:{...s,name:t.target.value})})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{style:x,children:"役職・肩書き"}),e.jsx("input",{className:"w-full px-6 py-3 text-sm focus:outline-none",style:u,placeholder:"例:チーフトリマー",value:a.role,onChange:t=>f(s=>({...s,role:t.target.value}))})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{style:x,htmlFor:"staff-booking-cutoff",children:"お客様の予約を受ける終わり"}),e.jsxs("select",{id:"staff-booking-cutoff",className:"w-full px-6 py-3 text-sm focus:outline-none",style:u,value:a.booking_cutoff,onChange:t=>f(s=>({...s,booking_cutoff:t.target.value})),children:[e.jsx("option",{value:"",children:"終業まで"}),U.map(t=>e.jsxs("option",{value:String(t),children:["終業の",t,"分前まで"]},t))]})]}),e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsx("label",{style:x,children:"LINE ユーザーID"}),e.jsx("input",{className:"w-full px-6 py-3 text-sm focus:outline-none",style:u,placeholder:"例:U1234567890abcdef",value:a.line_user_id,onChange:t=>f(s=>({...s,line_user_id:t.target.value}))})]}),e.jsxs("label",{className:"flex items-center gap-2.5 cursor-pointer",children:[e.jsx("input",{type:"checkbox",className:"w-4 h-4",style:{accentColor:"var(--gold-3)"},checked:a.is_active,onChange:t=>f(s=>({...s,is_active:t.target.checked}))}),e.jsx("span",{style:{fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:300,fontSize:"13px",color:"var(--ink)"},children:"稼働中にする"})]})]}),w&&e.jsx("p",{className:"text-xs px-3 py-2",style:{color:"#c0392b",background:"rgba(192,57,43,0.06)",borderRadius:"10px"},children:w}),e.jsx("button",{onClick:I,disabled:k||!i&&!a.name.trim(),className:"w-full py-3.5 rounded-[18px] text-sm disabled:opacity-50",style:{fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:400,background:"var(--ink-2)",color:"#fdfaf5",border:"0.5px solid rgba(47,158,143,0.3)"},children:k?"保存中...":"保存する"})]})}),S&&e.jsx("div",{className:"fixed inset-0 bg-black/50 z-50 flex items-center justify-center px-6",children:e.jsxs("div",{className:"w-full max-w-sm flex flex-col gap-4 p-6",style:{background:"var(--lux-white)",borderRadius:"24px"},children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-center",style:{fontFamily:"'Sora', sans-serif",fontSize:"18px",fontWeight:300,color:"var(--ink)"},children:"このスタッフを削除しますか?"}),e.jsx("p",{className:"text-xs text-center mt-1",style:{fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:300,color:"var(--muted)"},children:"削除したデータは元に戻せません。"})]}),e.jsxs("div",{className:"flex gap-3",children:[e.jsx("button",{onClick:()=>y(null),className:"flex-1 py-2.5 rounded-[12px] text-sm",style:{fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:300,color:"var(--muted)",border:"0.5px solid var(--cream-3)"},children:"キャンセル"}),e.jsx("button",{onClick:()=>A(S),disabled:g,className:"flex-1 py-2.5 rounded-[12px] text-sm disabled:opacity-50",style:{fontFamily:"'Zen Maru Gothic', sans-serif",fontWeight:400,background:"rgba(192,57,43,0.9)",color:"#fff"},children:g?"削除中…":"削除する"})]})]})})]})}export{xe as AdminStaffPage};

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.