PageSourceSearch

https://line-harness.neuroploom.workers.dev/assets/main-yXpynJVd.js

js line-harness.neuroploom.workers.dev collected 2026-10-03 08:08:22 UTC 17,498 bytes, 1 lines download raw bytes

1import{c as A,j as e,r as d}from"./client-auj285-g.js";let S=null;function I(s,a={}){return{Authorization:`Bearer ${s.idToken}`,...a}}function N(s,a){const n=new URL(s,window.location.origin);return n.searchParams.set("liffId",a.liffId),fetch(n.toString(),{headers:I(a)}).then(async t=>{if(!t.ok){const r=await t.text();let l=null;try{l=JSON.parse(r)}catch{}const m=new Error(`API ${t.status}`);throw m.status=t.status,m.body=l??r,m}return t.json()})}async function $(s,a,n,t={}){const r=new URL(s,window.location.origin);r.searchParams.set("liffId",n.liffId);const l=await fetch(r.toString(),{method:"POST",headers:I(n,{"Content-Type":"application/json",...t}),body:JSON.stringify(a)});if(!l.ok){const m=await l.text();let g=null;try{g=JSON.parse(m)}catch{}const u=new Error(`API ${l.status}`);throw u.status=l.status,u.body=g??m,u}return l.json()}function _(s){return new Date(s).toLocaleString("ja-JP",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",weekday:"short"})}function J(s){return new Date(s).toLocaleString("ja-JP",{year:"numeric",month:"2-digit",day:"2-digit",weekday:"short"})}function C(s){return new Date(s).toLocaleString("ja-JP",{hour:"2-digit",minute:"2-digit"})}function B(){return crypto.randomUUID()}function L(){return e.jsx("div",{className:"flex items-center justify-center py-16",children:e.jsx("div",{className:"eb-spinner"})})}function O({ctx:s,eventId:a,onPickSlot:n,onGoHistory:t}){const[r,l]=d.useState(null),[m,g]=d.useState([]),[u,p]=d.useState([]),[x,j]=d.useState(null),[i,h]=d.useState(!0);if(d.useEffect(()=>{let o=!1;async function y(){try{const[f,w]=await Promise.all([N(`/api/liff/events/${a}`,s),N(`/api/liff/events/${a}/slots`,s)]);if(o)return;l(f),g(w.items);try{const[P,D]=await Promise.all([N("/api/liff/events/me?tab=upcoming",s),N("/api/liff/events/me?tab=past",s)]);if(o)return;const T=[...P.items,...D.items];p(T.filter(k=>k.event_id===f.id&&(k.status==="requested"||k.status==="confirmed")))}catch{}}catch(f){o||j(f instanceof Error?f.message:String(f))}finally{o||h(!1)}}return y(),()=>{o=!0}},[s,a]),i)return e.jsx(L,{});if(x||!r){const y=(x==null?void 0:x.includes("404"))||(x==null?void 0:x.includes("not_found"))?"このイベントは現在受付を停止しています、または、ご利用中の LINE アカウントでは予約できません。":x??"イベントが見つかりません";return e.jsx("div",{className:"px-4 py-6 eb-fade-in",children:e.jsx("div",{className:"eb-card text-center",children:e.jsx("p",{className:"text-sm text-gray-700",children:y})})})}const c=r.max_bookings_per_friend,b=r.my_existing_booking;if(b&&c===1)return e.jsxs("div",{className:"pb-24 eb-fade-in",children:[r.image_url?e.jsx("img",{src:r.image_url,alt:"",className:"w-full h-auto bg-gray-100"}):e.jsx("div",{className:"w-full h-52 bg-gradient-to-br from-green-100 to-green-200"}),e.jsx("div",{className:"px-4 mt-4",children:e.jsxs("div",{className:"eb-card eb-card-success",children:[e.jsx("div",{className:"text-2xl mb-2",children:"✅"}),e.jsx("div",{className:"text-base font-bold text-gray-900 mb-1",children:"予約済みです"}),e.jsx("div",{className:"text-sm text-gray-700",children:_(b.slot_starts_at)}),e.jsx("button",{onClick:t,className:"eb-primary-btn mt-4",children:"予約履歴を見る"})]})})]});const v=c!=null&&u.length>=c;return e.jsxs("div",{className:"pb-24 eb-fade-in",children:[r.image_url?e.jsx("img",{src:r.image_url,alt:"",className:"w-full h-auto bg-gray-100"}):e.jsx("div",{className:"w-full h-52 bg-gradient-to-br from-green-100 to-green-200"}),e.jsxs("div",{className:"px-4 mt-4",children:[e.jsxs("div",{className:"eb-card",children:[e.jsx("h1",{className:"text-lg font-bold text-gray-900 leading-snug",children:r.name}),r.venue_name&&e.jsxs("div",{className:"mt-2 text-sm text-gray-700 flex items-start gap-1.5",children:[e.jsx("span",{children:"📍"}),e.jsx("span",{children:r.venue_name})]}),r.venue_url&&e.jsx("a",{href:r.venue_url,target:"_blank",rel:"noopener noreferrer",className:"mt-1 inline-block text-xs eb-line-green-text underline break-all",children:r.venue_url}),c!=null&&e.jsxs("div",{className:"mt-3 inline-flex items-center gap-1 eb-badge bg-gray-100 text-gray-700",children:["あなたの予約 ",u.length," / ",c]}),b&&e.jsxs("div",{className:"mt-3 text-xs eb-line-green-text",children:["✓ ",_(b.slot_starts_at)," の予約済みです"]})]}),r.description&&e.jsx("div",{className:"eb-card mt-3",children:e.jsx("div",{className:`text-sm whitespace-pre-wrap leading-relaxed text-gray-800 ${r.description_centered===1?"text-center":""}`,children:r.description})}),e.jsxs("div",{className:"mt-5",children:[e.jsx("h2",{className:"text-sm font-bold text-gray-900 mb-2 px-1",children:"日時を選択"}),m.length===0?e.jsx("div",{className:"eb-card text-center text-sm text-gray-500",children:"現在予約可能な枠はありません。"}):e.jsx("ul",{className:"space-y-2",children:m.map(o=>{const y=o.remaining!=null&&o.remaining<=0,f=y||v;return e.jsx("li",{children:e.jsxs("button",{disabled:f,onClick:()=>n(o,r),className:"eb-slot-btn",children:[e.jsxs("span",{className:"flex flex-col items-start",children:[e.jsx("span",{className:"text-xs opacity-70",children:J(o.starts_at)}),e.jsxs("span",{className:"text-base",children:[C(o.starts_at)," 〜 ",C(o.ends_at)]})]}),e.jsx("span",{className:"text-xs font-medium",children:y?"満員":o.capacity==null?"定員なし":`残 ${o.remaining}`})]})},o.id)})}),v&&e.jsxs("p",{className:"mt-3 text-xs text-red-600 px-1",children:["このイベントへの予約上限(",c,")に達しています。"]})]}),e.jsx("div",{className:"mt-6 text-center",children:e.jsx("button",{onClick:t,className:"text-sm eb-line-green-text underline",children:"予約履歴を見る"})})]})]})}function q({ctx:s,event:a,slot:n,onBack:t,onDone:r}){const[l,m]=d.useState(""),[g,u]=d.useState(!1),[p,x]=d.useState(null),[j]=d.use
1State(B);async function i(){var h;if(l.length>5e3){x("備考は 5000 字以内で入力してください");return}u(!0),x(null);try{const c=await $(`/api/liff/events/${a.id}/bookings`,{slot_id:n.id,customer_note:l||null},s,{"Idempotency-Key":j});r(c.status)}catch(c){const b=c,v=(h=b.body)==null?void 0:h.error,o=(()=>{var y;switch(v){case"slot_full":return"すでに満員になりました。別の日時をお選びください。";case"over_friend_limit":return"このイベントへの予約上限に達しています。";case"slot_started":return"この枠は既に開始されています。";case"slot_inactive":return"この枠は受付を締め切りました。";case"event_unpublished":return"このイベントは現在受付を停止しています。";case"unauthorized":case"friend_not_found":return"LINE 認証に失敗しました。一度トークルームに戻り、友だち追加が完了していることを確認してください。";case"idempotent_in_progress":return"前回のリクエストを処理中です。少しお待ちください。";case"duplicate_friend_booking":{const f=(y=b.body)==null?void 0:y.existing,w=f!=null&&f.slot_starts_at?_(f.slot_starts_at):"";return`このイベントは既に予約済みです${w?`(${w})`:""}。予約履歴から確認できます。`}default:return c instanceof Error?c.message:String(c)}})();x(o)}finally{u(!1)}}return e.jsxs("div",{className:"px-4 py-4 pb-24 space-y-4 eb-slide-up",children:[e.jsxs("button",{onClick:t,className:"eb-back-btn",children:[e.jsx("span",{"aria-hidden":!0,children:"←"}),"戻る"]}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-base font-bold text-gray-900",children:"予約内容のご確認"}),e.jsx("p",{className:"text-xs text-gray-500 mt-1",children:"最後にご確認ください"})]}),e.jsx("div",{className:"eb-card",children:e.jsxs("dl",{className:"space-y-3 text-sm",children:[e.jsx(E,{label:"イベント",value:a.name}),e.jsx(E,{label:"日時",value:_(n.starts_at)}),a.venue_name&&e.jsx(E,{label:"会場",value:a.venue_name})]})}),a.requires_approval===1&&e.jsx("div",{className:"bg-amber-50 border border-amber-200 text-amber-900 text-xs rounded-xl p-3",children:"このイベントは承認制です。受付後、運営が承認するまでお待ちください。"}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-gray-700 mb-1.5",children:"備考(任意)"}),e.jsx("textarea",{value:l,onChange:h=>m(h.target.value),rows:4,maxLength:5e3,placeholder:"質問や伝えたいことがあれば...",className:"w-full border border-gray-300 rounded-xl p-3 text-sm bg-white"}),e.jsxs("div",{className:"text-xs text-gray-500 text-right mt-1",children:[l.length," / 5000"]})]}),p&&e.jsx("div",{className:"bg-red-50 border border-red-200 text-red-700 p-3 rounded-xl text-sm",children:p}),e.jsx("button",{onClick:i,disabled:g,className:"eb-primary-btn",children:g?"送信中...":"予約をリクエスト"}),e.jsx("button",{onClick:t,disabled:g,className:"eb-secondary-btn",children:"戻る"})]})}function E({label:s,value:a,valueClassName:n}){return e.jsxs("div",{className:"flex items-baseline justify-between gap-3",children:[e.jsx("dt",{className:"text-xs text-gray-500 shrink-0",children:s}),e.jsx("dd",{className:`text-right ${n??"text-gray-900"}`,children:a})]})}function z({status:s,onGoHistory:a}){const n=s==="requested";return e.jsx("div",{className:"px-4 py-10 text-center eb-slide-up",children:e.jsxs("div",{className:"eb-card",children:[e.jsx("div",{className:"text-5xl mb-3",children:n?"⏳":"✅"}),e.jsx("h1",{className:"text-lg font-bold mb-2 text-gray-900",children:n?"受付しました":"予約が確定しました"}),e.jsx("p",{className:"text-sm text-gray-600 mb-6 leading-relaxed",children:n?"運営の承認をお待ちください。承認されると LINE でお知らせします。":"予約が確定しました。LINE で詳細をお送りしました。"}),e.jsx("button",{onClick:a,className:"eb-primary-btn",children:"予約履歴を見る"})]})})}const R={requested:{text:"承認待ち",cls:"bg-amber-100 text-amber-800"},confirmed:{text:"確定",cls:"bg-green-100 text-green-800"},rejected:{text:"見送り",cls:"bg-gray-200 text-gray-700"},cancelled:{text:"キャンセル",cls:"bg-gray-100 text-gray-600"},expired:{text:"期限切れ",cls:"bg-gray-100 text-gray-500"},attended:{text:"参加済",cls:"bg-blue-100 text-blue-800"},no_show:{text:"不参加",cls:"bg-red-100 text-red-700"}};function U(s){return s.status!=="requested"&&s.status!=="confirmed"||s.cancel_deadline_hours_before==null?!1:new Date(s.slot_starts_at).getTime()-s.cancel_deadline_hours_before*36e5>Date.now()}async function F(s,a){await $(`/api/liff/events/me/${a}/cancel`,{},s)}function M({ctx:s,initialTab:a,onOpenDetail:n}){const[t,r]=d.useState(a??"upcoming"),[l,m]=d.useState([]),[g,u]=d.useState(!0),[p,x]=d.useState(null);async function j(){u(!0),x(null);try{const i=await N(`/api/liff/events/me?tab=${t}`,s);m(i.items)}catch(i){x(i instanceof Error?i.message:String(i))}finally{u(!1)}}return d.useEffect(()=>{j()},[t]),e.jsxs("div",{className:"pb-20 eb-fade-in",children:[e.jsx("div",{className:"sticky top-12 z-10 bg-white border-b border-gray-200",children:e.jsx("div",{className:"flex",children:["upcoming","past"].map(i=>e.jsx("button",{onClick:()=>r(i),className:`flex-1 py-3 text-sm font-medium border-b-2 ${t===i?"border-[#06C755] eb-line-green-text":"border-transparent text-gray-500"}`,children:i==="upcoming"?"これから":"過去"},i))})}),e.jsxs("div",{className:"px-4 py-4 space-y-4",children:[p&&e.jsx("div",{className:"bg-red-50 border border-red-200 text-red-700 p-3 rounded-xl text-sm",children:p}),g?e.jsx(L,{}):l.length===0?e.jsx("div",{className:"eb-card text-center text-sm text-gray-500 py-8",children:t==="upcoming"?"これからの予約はありません":"過去の予約はありません"}):l.map(i=>{const h=R[i.status]??{text:i.status,cls:"bg-gray-100"};return e.jsx("button",{type:"button",onClick:()=>n(i.id,t),className:"eb-card !p-0 overflow-hidden w-full text-left hover:bg-gray-50 active:bg-gray-100 transition-colors",children:e.jsxs("div",{className:"flex",children:[i.event_image_url?e.jsx("img",{src:i.event_image_url,alt:"",className:"w-24 h-24 object-cover bg-gray-100 shrink-0"}):e.jsx("div",{className:"w-24 h-24 bg-gradient-to-br from-green-100 to-green-200 shrink-0"}),e.jsxs("div",{className:"flex-1 p-4 min-w-0",children:[e.jsxs("div",{className:"flex items-start justify-between gap-2",children:[e.jsx("div",{className:"font-semibold text-sm line-clamp-2 text-gray-900",children:i.event_name}),e.jsx("span",{className:`eb-badge ${h.cls} shrink-0`,children:h.text})]}),e.jsx("div",{className:"text-xs text-gray-600 mt-1.5",children:_(i.slot_starts_at)}),i.venue_name&&e.jsxs("div",{className:"text-xs text-gray-500 truncate mt-0.5",children:["📍 ",i.venue_name]})]}),e.jsx("div",{className:"flex items-center pr-3 text-gray-400 shrink-0",children:"›"})]})},i.id)})]})]})}function H({ctx:s,bookingId:a,onBack:n}){const[t,r]=d.useState(null),[l,m]=d.useState(!0),[g,u]=d.useState(null),[p,x]=d.useState(!1);d.useEffect(()=>{let c=!1;return(async()=>{try{const b=await N(`/api/liff/events/me/${a}`,s);if(c)return;r(b)}catch(b){c||u(b instanceof Error?b.message:String(b))}finally{c||m(!1)}})(),()=>{c=!0}},[s,a]);async function j(){if(t&&confirm(`「${t.event_name}」の予約をキャンセルしますか?`)){x(!0),u(null);try{await F(s,t.id),n()}catch(c){const b=c,v=(()=>{var o;switch((o=b.body)==null?void 0:o.error){case"cancel_deadline_passed":return"キャンセル期限を過ぎています。";case"cancel_not_allowed":return"このイベントは LIFF からのキャンセル不可です。LINE で運営にご連絡ください。";
1case"invalid_state":return"この予約はキャンセルできない状態です。";default:return c instanceof Error?c.message:String(c)}})();u(v)}finally{x(!1)}}}if(l)return e.jsx("div",{className:"pb-24 eb-fade-in",children:e.jsx("div",{className:"px-4 py-6",children:e.jsx(L,{})})});if(!t)return e.jsx("div",{className:"pb-24 eb-fade-in",children:e.jsxs("div",{className:"px-4 py-6 space-y-3",children:[g&&e.jsx("div",{className:"bg-red-50 border border-red-200 text-red-700 p-3 rounded-xl text-sm",children:g}),e.jsx("button",{onClick:n,className:"eb-primary-btn",children:"予約履歴へ戻る"})]})});const i=t.status==="confirmed"&&t.confirmation_message_extra!=null&&t.confirmation_message_extra.trim().length>0,h=U(t);return e.jsxs("div",{className:"pb-24 eb-fade-in",children:[t.event_image_url?e.jsx("img",{src:t.event_image_url,alt:"",className:"w-full h-auto bg-gray-100"}):e.jsx("div",{className:"w-full h-52 bg-gradient-to-br from-green-100 to-green-200"}),e.jsxs("div",{className:"px-4 mt-4 space-y-4",children:[e.jsxs("div",{className:"eb-card space-y-2",children:[e.jsx("h1",{className:"text-lg font-bold text-gray-900 leading-snug",children:t.event_name}),e.jsxs("div",{className:"text-sm text-gray-700",children:["📅 ",_(t.slot_starts_at)]}),t.venue_name&&e.jsxs("div",{className:"text-sm text-gray-700",children:["📍 ",t.venue_name]}),t.venue_url&&e.jsx("a",{href:t.venue_url,target:"_blank",rel:"noopener noreferrer",className:"block text-sm text-blue-600 break-all underline",children:t.venue_url}),t.event_description&&e.jsx("div",{className:"mt-2 text-sm text-gray-800 whitespace-pre-wrap",children:t.event_description})]}),i&&e.jsxs("div",{className:"eb-card bg-yellow-50 border border-yellow-200",children:[e.jsx("div",{className:"text-sm font-semibold text-yellow-900 mb-2",children:"ご予約者向け情報"}),e.jsx("div",{className:"text-sm text-gray-800 whitespace-pre-wrap break-all",children:t.confirmation_message_extra})]}),g&&e.jsx("div",{className:"bg-red-50 border border-red-200 text-red-700 p-3 rounded-xl text-sm",children:g}),h&&e.jsx("button",{onClick:j,disabled:p,className:"w-full py-3 border border-red-300 text-red-600 rounded-xl text-sm font-medium disabled:opacity-50 hover:bg-red-50 active:bg-red-100 transition-colors",children:p?"キャンセル中...":"この予約をキャンセルする"}),e.jsx("button",{onClick:n,className:"w-full py-3 text-sm text-gray-500",children:"← 予約履歴へ戻る"})]})]})}function G({ctx:s,initial:a}){const[n,t]=d.useState(a),r=(()=>{switch(n.kind){case"detail":return"イベント予約";case"confirm":return"ご予約内容の確認";case"done":return"完了";case"history":return"予約履歴";case"booking-detail":return"予約詳細"}})();return e.jsxs("div",{className:"min-h-screen",style:{background:"#f5f5f5"},children:[e.jsx("header",{className:"px-4 py-3 text-white text-center font-bold sticky top-0 z-20",style:{background:"#06C755",fontSize:"15px"},children:r}),e.jsxs("main",{className:"max-w-md mx-auto",children:[n.kind==="detail"&&e.jsx(O,{ctx:s,eventId:n.eventId,onPickSlot:(l,m)=>t({kind:"confirm",event:m,slot:l}),onGoHistory:()=>t({kind:"history"})}),n.kind==="confirm"&&e.jsx(q,{ctx:s,event:n.event,slot:n.slot,onBack:()=>t({kind:"detail",eventId:n.event.id}),onDone:l=>t({kind:"done",status:l})}),n.kind==="done"&&e.jsx(z,{status:n.status,onGoHistory:()=>t({kind:"history"})}),n.kind==="history"&&e.jsx(M,{ctx:s,initialTab:n.tab,onOpenDetail:(l,m)=>t({kind:"booking-detail",bookingId:l,fromTab:m})}),n.kind==="booking-detail"&&e.jsx(H,{ctx:s,bookingId:n.bookingId,onBack:()=>t({kind:"history",tab:n.fromTab})})]})]})}function Q(s,a,n){document.body.classList.add("eb-active"),S||(S=A.createRoot(s)),S.render(e.jsx(d.StrictMode,{children:e.jsx(G,{ctx:a,initial:n})}))}export{Q as mountEventBooking};

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.