PageSourceSearch

https://line-tabizemi.touch929.workers.dev/assets/index-eRU52PE4.js

js line-tabizemi.touch929.workers.dev collected 2026-10-03 08:08:20 UTC 45,267 bytes, 410 lines download raw bytes

1const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/main-B-S1uEee.js","assets/client-auj285-g.js","assets/main-BJmpy10s.css","assets/main-Kg_lE8TC.js","assets/main-CRNZPlyW.css"])))=>i.map(i=>d[i]);
2(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))o(i);new MutationObserver(i=>{for(const r of i)if(r.type==="childList")for(const s of r.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&o(s)}).observe(document,{childList:!0,subtree:!0});function n(i){const r={};return i.integrity&&(r.integrity=i.integrity),i.referrerPolicy&&(r.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?r.credentials="include":i.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function o(i){if(i.ep)return;i.ep=!0;const r=n(i);fetch(i.href,r)}})();const re="modulepreload",se=function(e){return"/"+e},K={},ne=function(t,n,o){let i=Promise.resolve();if(n&&n.length>0){let s=function(d){return Promise.all(d.map(l=>Promise.resolve(l).then(h=>({status:"fulfilled",value:h}),h=>({status:"rejected",reason:h}))))};document.getElementsByTagName("link");const c=document.querySelector("meta[property=csp-nonce]"),f=(c==null?void 0:c.nonce)||(c==null?void 0:c.getAttribute("nonce"));i=s(n.map(d=>{if(d=se(d),d in K)return;K[d]=!0;const l=d.endsWith(".css"),h=l?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${d}"]${h}`))return;const p=document.createElement("link");if(p.rel=l?"stylesheet":re,l||(p.as="script"),p.crossOrigin="",p.href=d,f&&p.setAttribute("nonce",f),document.head.appendChild(p),l)return new Promise((w,k)=>{p.addEventListener("load",w),p.addEventListener("error",()=>k(new Error(`Unable to preload CSS for ${d}`)))})}))}function r(s){const c=new Event("vite:preloadError",{cancelable:!0});if(c.payload=s,window.dispatchEvent(c),!c.defaultPrevented)throw s}return i.then(s=>{for(const c of s||[])c.status==="rejected"&&r(c.reason);return t().catch(r)})},_={},q=(_==null?void 0:_.VITE_CALENDAR_CONNECTION_ID)||"",b={currentYear:new Date().getFullYear(),currentMonth:new Date().getMonth(),selectedDate:null,slots:[],selectedSlot:null,profile:null,friendId:null,loading:!1,submitting:!1};function oe(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function Y(e,t){return fetch(e,{...t,headers:{"Content-Type":"application/json",...t==null?void 0:t.headers}})}function N(e){const t=new Date(e);return`${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`}function M(e){const t=new Date(`${e}T00:00:00`),n=["日","月","火","水","木","金","土"];return`${t.getFullYear()}年${t.getMonth()+1}月${t.getDate()}日(${n[t.getDay()]})`}function O(){return document.getElementById("app")}function ae(e,t){return new Date(e,t+1,0).getDate()}function ce(e,t){return new Date(e,t,1).getDay()}function le(e,t,n){const o=new Date;return o.getFullYear()===e&&o.getMonth()===t&&o.getDate()===n}function de(e,t,n){const o=new Date,i=new Date(e,t,n);return o.setHours(0,0,0,0),i<o}function fe(e,t,n){return`${e}-${String(t+1).padStart(2,"0")}-${String(n).padStart(2,"0")}`}function ue(){const{currentYear:e,currentMonth:t,selectedDate:n}=b,o=ae(e,t),i=ce(e,t),r=["日","月","火","水","木","金","土"];let s=`
3    <div class="booking-calendar">
4      <div class="calendar-header">
5        <button class="cal-nav" data-action="prev-month">&lt;</button>
6        <span class="cal-title">${e}年${t+1}月</span>
7        <button class="cal-nav" data-action="next-month">&gt;</button>
8      </div>
9      <div class="cal-weekdays">
10        ${r.map((c,f)=>`<span class="${f===0?"sun":f===6?"sat":""}">${c}</span>`).join("")}
11      </div>
12      <div class="cal-days">
13  `;for(let c=0;c<i;c++)s+='<span class="cal-day empty"></span>';for(let c=1;c<=o;c++){const f=fe(e,t,c),d=de(e,t,c),l=le(e,t,c),p=["cal-day",d?"past":"active",l?"today":"",n===f?"selected":"",new Date(e,t,c).getDay()===0?"sun":"",new Date(e,t,c).getDay()===6?"sat":""].filter(Boolean).join(" ");s+=`<span class="${p}" ${d?"":`data-date="${f}"`}>${c}</span>`}return s+="</div></div>",s}function me(){const{slots:e,selectedDate:t,selectedSlot:n,loading:o}=b;if(!t)return"";if(o)return`
14      <div class="slots-section">
15        <h3>${M(t)}</h3>
16        <div class="slots-loading">
17          <div class="loading-spinner"></div>
18          <p>空き状況を確認中...</p>
19        </div>
20      </div>
21    `;if(e.length===0)return`
22      <div class="slots-section">
23        <h3>${M(t)}</h3>
24        <p class="no-slots">この日は予約枠がありません</p>
25      </div>
26    `;const i=e.map(r=>{const s=(n==null?void 0:n.startAt)===r.startAt;return`<button class="${r.available?s?"slot-btn selected":"slot-btn available":"slot-btn full"}" ${r.available?`data-start="${r.startAt}" data-end="${r.endAt}"`:"disabled"}>${N(r.startAt)} - ${N(r.endAt)}</button>`}).join("");return`
27    <div class="slots-section">
28      <h3>${M(t)}</h3>
29      <div class="slots-grid">${i}</div>
30    </div>
31  `}function pe(){const{selectedSlot:e,selectedDate:t,profile:n}=b;return!e||!t?"":`
32    <div class="confirm-section">
33      <div class="confirm-card">
34        <h3>予約内容の確認</h3>
35        <div class="confirm-details">
36          <div class="confirm-row">
37            <span class="confirm-label">日付</span>
38            <span class="confirm-value">${M(t)}</span>
39          </div>
40          <div class="confirm-row">
41            <span class="confirm-label">時間</span>
42            <span class="confirm-value">${N(e.startAt)} - ${N(e.endAt)}</span>
43          </div>
44          <div class="confirm-row">
45            <span class="confirm-label">お名前</span>
46            <span class="confirm-value">${n?oe(n.displayName):"---"}</span>
47          </div>
48        </div>
49        <button class="book-btn" data-action="confirm-booking">予約を確定する</button>
50      </div>
51    </div>
52  `}function B(){const e=O();e.innerHTML=`
53    <div class="booking-page">
54      <div class="booking-header">
55        <h1>予約</h1>
56        <p>ご希望の日時をお選びください</p>
57      </div>
58      ${ue()}
59      ${me()}
60      ${pe()}
61    </div>
62  `,be()}function ge(e,t){const n=O();n.innerHTML=`
63    <div class="booking-page">
64      <div class="success-card">
65        <div class="success-icon">✓</div>
66        <h2>予約が完了しました</h2>
67        <div class="confirm-details">
68          <div class="confirm-row">
69            <span class="confirm-label">日付</span>
70            <span class="confirm-value">${M(e)}</span>
71          </div>
72          <div class="confirm-row">
73            <span class="confirm-label">時間</span>
74            <span class="confirm-value">${N(t.startAt)} - ${N(t.endAt)}</span>
75          </div>
76        </div>
77        <p class="success-message">ご予約ありがとうございます。<br>当日のお越しをお待ちしております。</p>
78        <button class="close-btn" data-action="close">閉じる</button>
79      </div>
80    </div>
81  `;const o=n.querySelector('[data-action="close"]');o==null||o.addEventListener("click",()=>{liff.isInClient()?liff.closeWindow():window.close()})}function he(e){var n;const t=O();t.innerHTML=`
82    <div class="booking-page">
83      <div class="card">
84        <h2 style="color: #e53e3e;">エラー</h2>
85        <p class="error">${oe(e)}</p>
86        <button class="close-btn" data-action="retry" style="margin-top:16px;">やり直す</button>
87      </div>
88    </div>
89  `,(n=t.querySelector('[data-action="retry"]'))==null||n.addEventListener("click",()=>{b.selectedDate=null,b.selectedSlot=null,b.slots=[],B()})}function be(){const e=O();e.querySelectorAll(".cal-nav").forEach(n=>{n.addEventListener("click",()=>{n.dataset.action==="prev-month"?(b.currentMonth--,b.currentMonth<0&&(b.currentMonth=11,b.currentYear--)):(b.currentMonth++,b.currentMonth>11&&(b.currentMonth=0,b.currentYear++)),b.selectedDate=null,b.selectedSlot=null,b.slots=[],B()})}),e.querySelectorAll(".cal-day.active").forEach(n=>{n.addEventListener("click",()=>{const o=n.dataset.date;o&&(b.selectedDate=o,b.selectedSlot=null,b.slots=[],b.loading=!0,B(),ye(o))})}),e.querySelectorAll(".slot-btn.available").forEach(n=>{n.addEventListener("click",()=>{const o=n.dataset.start,i=n.dataset.end;b.selectedSlot={startAt:o,endAt:i,available:!0},B(),setTimeout(()=>{const r=O().querySelector(".confirm-section");r==null||r.scrollIntoView({behavior:"smooth"})},50)})});const t=e.querySelector('[data-action="confirm-booking"]');t==null||t.addEventListener("click",()=>xe())}async function ye(e){try{const t=new URLSearchParams({date:e});q&&t.set("connectionId",q);const n=await Y(`/api/integrations/google-calendar/slots?${t}`);if(!n.ok)throw new Error("スロット取得に失敗しました");const o=await n.json();if(!o.success)throw new Error("スロット取得に失敗しました");b.slots=o.data}catch(t){b.slots=[],console.error("fetchSlots error:",t)}finally{b.loading=!1,B()}}async function xe(){const{selectedSlot:e,selectedDate:t,profile:n,friendId:o}=b;if(!e||!t||!n||b.submitting)return;b.submitting=!0;const i=O().querySelector('[data-action="confirm-booking"]');i&&(i.disabled=!0,i.textContent="送信中...");try{const r={title:`${n.displayName}様 予約`,startAt:e.startAt,endAt:e.endAt};q&&(r.connectionId=q),o&&(r.friendId=o);const s=await Y("/api/integrations/google-calendar/book",{method:"POST",body:JSON.stringify(r)});if(!s.ok){const c=await s.json().catch(()=>null);throw new Error((c==null?void 0:c.error)||"予約に失敗しました")}ge(t,e)}catch(r){b.submitting=!1,he(r instanceof Error?r.message:"予約に失敗しました")}}async function ve(){const e=await liff.getProfile();b.profile=e;const t="lh_uuid";try{b.friendId=localStorage.getItem(t)}catch{}const n=liff.getIDToken();if(n){const o=b.friendId;Y("/api/liff/link",{method:"POST",body:JSON.stringify({idToken:n,displayName:e.displayName,existingUuid:o})}).then(async i=>{var r;if(i.ok){const s=await i.json();if((r=s==null?void 0:s.data)!=null&&r.userId)try{localStorage.setItem(t,s.data.userId),b.friendId=s.data.userId}catch{}}}).catch(()=>{})}B()}const Q="lh_uuid",m={formDef:null,xHarnessBaseUrl:null,profile:null,friendId:null,
89submitting:!1,verifiedXUsername:"",refTrackedLinkId:null};let F=!1;function g(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function C(e,t){return fetch(e,{...t,headers:{"Content-Type":"application/json",...t==null?void 0:t.headers}})}function E(){return document.getElementById("app")}function J(e){const t=e.required?" required":"",n=e.placeholder?` placeholder="${g(e.placeholder)}"`:"",o=e.required?'<span class="required-mark">*</span>':"";if(e.name==="x_username")return`
90      <div class="form-field">
91        <label class="form-label" for="field-${g(e.name)}">
92          ${g(e.label)}${o}
93        </label>
94        <div class="x-autocomplete-wrap">
95          <input
96            type="text"
97            name="${g(e.name)}"
98            id="field-${g(e.name)}"
99            class="form-input x-autocomplete-input"
100            placeholder="${e.placeholder?g(e.placeholder):"X ID or 名前で検索(3文字以上)"}"
101            autocomplete="off"
102            ${t} />
103          <ul class="x-suggest-list" id="x-suggest-list" hidden></ul>
104          <p class="x-suggest-hint" id="x-suggest-hint" hidden>3文字以上入力してください</p>
105        </div>
106        <div class="x-conditions" id="x-conditions" hidden></div>
107        <p class="x-conditions-result" id="x-conditions-result" hidden></p>
108      </div>
109    `;let i="";switch(e.type){case"textarea":i=`<textarea
110        name="${g(e.name)}"
111        id="field-${g(e.name)}"
112        class="form-textarea"
113        rows="4"
114        ${n}${t}></textarea>`;break;case"select":{const r=(e.options??[]).map(s=>`<option value="${g(s)}">${g(s)}</option>`).join("");i=`<select
115        name="${g(e.name)}"
116        id="field-${g(e.name)}"
117        class="form-select"${t}>
118        <option value="">選択してください</option>
119        ${r}
120      </select>`;break}case"radio":{const r=(e.options??[]).map(s=>`<label class="radio-label">
121              <input type="radio" name="${g(e.name)}" value="${g(s)}"${t} />
122              ${g(s)}
123            </label>`).join("");i=`<div class="radio-group${e.columns===2?" two-col":""}">${r}</div>`;break}case"checkbox":{const r=(e.options??[]).map(s=>`<label class="checkbox-label">
124              <input type="checkbox" name="${g(e.name)}" value="${g(s)}" />
125              ${g(s)}
126            </label>`).join("");i=`<div class="checkbox-group${e.columns===2?" two-col":""}">${r}</div>`;break}default:i=`<input
127        type="${g(e.type)}"
128        name="${g(e.name)}"
129        id="field-${g(e.name)}"
130        class="form-input"
131        ${n}${t} />`;break}return`
132    <div class="form-field">
133      <label class="form-label" for="field-${g(e.name)}">
134        ${g(e.label)}${o}
135      </label>
136      ${i}
137    </div>
138  `}function we(){if(document.getElementById("form-styles"))return;const e=document.createElement("style");e.id="form-styles",e.textContent=`
139    .form-page { max-width: 480px; margin: 0 auto; padding: 16px; }
140    .form-header { text-align: center; margin-bottom: 24px; }
141    .form-header h1 { font-size: 20px; color: #333; margin-bottom: 8px; }
142    .form-description { font-size: 14px; color: #999; }
143    .form-profile { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 12px; }
144    .form-profile img { width: 36px; height: 36px; border-radius: 50%; }
145    .form-profile span { font-size: 14px; font-weight: 600; }
146    .form-body { background: #fff; border-radius: 12px; padding: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); }
147    .form-field { margin-bottom: 20px; }
148    .form-label { display: block; font-size: 14px; font-weight: 600; color: #333; margin-bottom: 6px; }
149    .required-mark { color: #e53e3e; margin-left: 2px; }
150    .form-input, .form-textarea, .form-select {
151      width: 100%; padding: 12px; border: 1.5px solid #e0e0e0; border-radius: 8px;
152      font-size: 16px; font-family: inherit; background: #fafafa;
153      transition: border-color 0.15s; box-sizing: border-box;
154      -webkit-appearance: none;
155    }
156    .form-input:focus, .form-textarea:focus, .form-select:focus {
157      outline: none; border-color: #06C755; background: #fff;
158    }
159    .form-textarea { resize: vertical; min-height: 80px; }
160    .form-select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M6 8L1 3h10z'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 12px center; }
161    .radio-group, .checkbox-group { display: flex; flex-direction: column; gap: 10px; }
162    .radio-group.two-col, .checkbox-group.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
163    .radio-label, .checkbox-label {
164      display: flex; align-items: center; gap: 8px; font-size: 15px; color: #333;
165      padding: 10px 12px; background: #fafafa; border-radius: 8px; border: 1.5px solid #e0e0e0;
166      cursor: pointer; transition: border-color 0.15s;
167    }
168    .radio-label:has(input:checked), .checkbox-label:has(input:checked) {
169      border-color: #06C755; background: #e8faf0;
170    }
171    .radio-label input, .checkbox-label input { accent-color: #06C755; width: 18px; height: 18px; }
172    .radio-label input[type="radio"] { appearance: none; -webkit-appearance: none; width: 18px; height: 18px; border: 2px solid #ccc; border-radius: 50%; background: #fff; cursor: pointer; }
173    .radio-label input[type="radio"]:checked { background: #fff; border-color: #06C755; border-width: 5px; }
174    .submit-btn {
175      width: 100%; padding: 14px; border: none; border-radius: 8px;
176      background: #06C755; color: #fff; font-size: 16px; font-weight: 700;
177      cursor: pointer; font-family: inherit; margin-top: 8px; transition: opacity 0.15s;
178    }
179    .submit-btn:active { opacity: 0.85; }
180    .submit-btn:disabled { background: #bbb;
180 cursor: not-allowed; }
181    .form-error { color: #e53e3e; font-size: 12px; margin-top: 4px; }
182    .x-loading-spinner {
183      width: 28px; height: 28px; border: 3px solid #333; border-top-color: #1D9BF0;
184      border-radius: 50%; animation: x-spin 0.8s linear infinite;
185    }
186    @keyframes x-spin { to { transform: rotate(360deg); } }
187    .x-autocomplete-wrap { position: relative; }
188    .x-suggest-list {
189      position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 100;
190      background: #1a1a1a; border: 1.5px solid #333; border-radius: 8px;
191      list-style: none; margin: 0; padding: 4px 0; box-shadow: 0 4px 12px rgba(0,0,0,0.4);
192      max-height: 240px; overflow-y: auto;
193    }
194    .x-suggest-item {
195      display: flex; align-items: center; gap: 10px;
196      padding: 10px 12px; cursor: pointer; transition: background 0.1s;
197    }
198    .x-suggest-item:hover, .x-suggest-item.focused { background: #2a2a2a; }
199    .x-suggest-avatar {
200      width: 32px; height: 32px; border-radius: 50%; object-fit: cover; flex-shrink: 0;
201      background: #333;
202    }
203    .x-suggest-avatar-placeholder {
204      width: 32px; height: 32px; border-radius: 50%; background: #444;
205      display: flex; align-items: center; justify-content: center;
206      font-size: 14px; color: #aaa; flex-shrink: 0;
207    }
208    .x-suggest-names { display: flex; flex-direction: column; overflow: hidden; }
209    .x-suggest-display { font-size: 14px; font-weight: 600; color: #f0f0f0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
210    .x-suggest-username { font-size: 12px; color: #888; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
211    .x-suggest-hint { font-size: 12px; color: #888; margin-top: 4px; }
212    .x-conditions-card {
213      margin-top: 12px;
214      padding: 16px;
215      background: #111;
216      border-radius: 12px;
217      border: 1px solid #222;
218    }
219    .x-condition-row {
220      display: flex;
221      align-items: center;
222      gap: 10px;
223      padding: 8px 0;
224      border-bottom: 1px solid #1a1a1a;
225      font-size: 14px;
226      color: #ccc;
227    }
228    .x-condition-row:last-child { border-bottom: none; }
229    .x-condition-check {
230      width: 28px;
231      height: 28px;
232      border-radius: 50%;
233      display: flex;
234      align-items: center;
235      justify-content: center;
236      font-size: 14px;
237      font-weight: bold;
238      flex-shrink: 0;
239    }
240    .x-condition-check.pass {
241      background: rgba(6, 199, 85, 0.15);
242      color: #06C755;
243      border: 2px solid #06C755;
244    }
245    .x-condition-check.fail {
246      background: rgba(229, 62, 62, 0.15);
247      color: #e53e3e;
248      border: 2px solid #e53e3e;
249    }
250    .x-condition-check.na {
251      background: rgba(255,255,255,0.05);
252      color: #555;
253      border: 2px solid #333;
254    }
255    .x-condition-check.checking {
256      background: rgba(255,255,255,0.05);
257      color: #888;
258      border: 2px solid #444;
259    }
260    .x-condition-check.checking .spin {
261      display: inline-block;
262      animation: spin 1s linear infinite;
263      font-size: 12px;
264    }
265    @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
266    .x-conditions-summary {
267      margin-top: 12px;
268      padding: 10px 16px;
269      border-radius: 8px;
270      font-size: 14px;
271      font-weight: 600;
272      text-align: center;
273    }
274    .x-conditions-summary.pass {
275      background: rgba(6, 199, 85, 0.1);
276      color: #06C755;
277      border: 1px solid rgba(6, 199, 85, 0.3);
278    }
279    .x-conditions-summary.fail {
280      background: rgba(229, 62, 62, 0.1);
281      color: #e53e3e;
282      border: 1px solid rgba(229, 62, 62, 0.3);
283    }
284    .form-success { text-align: center; padding: 40px 20px; }
285    .form-success .check { width: 64px; height: 64px; border-radius: 50%; background: #06C755; color: #fff; font-size: 32px; line-height: 64px; margin: 0 auto 16px; }
286    .form-success h2 { font-size: 20px; color: #06C755; margin-bottom: 12px; }
287    .form-success p { font-size: 14px; color: #666; line-height: 1.6; }
288  `,document.head.appendChild(e)}function ke(){var d;const{formDef:e,profile:t}=m;if(!e)return;we();const n=E(),o=e.hideProfile||!(t!=null&&t.pictureUrl)?"":`<div class="form-profile">
289        <img src="${t.pictureUrl}" alt="" />
290        <span>${g(t.displayName)} さん</span>
291      </div>`,i=e.fields.filter(l=>l.name!=="x_username"),r=e.fields.find(l=>l.name==="x_username"),s=!!r&&!!e.onSubmitWebhookUrl,c=i.map(J).join(""),f=r?J(r):"";if(s)n.innerHTML=`
292      <div class="form-page">
293        <div class="form-header">
294          <h1>${g(e.name).replace(/\\n|\n/g,"<br>")}</h1>
295          ${e.description&&!e.onSubmitWebhookUrl?`<p class="form-description">${g(e.description).replace(/\\n|\n/g,"<br>")}</p>`:""}
296          ${o}
297        </div>
298        <!-- Page 1: Survey -->
299        <div id="form-page-1">
300          <form id="survey-form" class="form-body" novalidate>
301            ${c}
302            <button type="submit" class="submit-btn" id="nextBtn">次へ →</button>
303          </form>
304        </div>
305        <!-- Page 2: X-Link -->
306        <div id="form-page-2" hidden>
307          <div class="form-header" style="padding-top:0">
308            <h1>X-Link で受け取り</h1>
309          </div>
310          <form id="liff-form" class="form-body" novalidate>
311            ${f}
312            <button type="submit" class="submit-btn" id="submitBtn">X Harness を受け取る</button>
313          </form>
314        </div>
315      </div>
316    `,(d=document.getElementById("survey-form"))==null||d.addEventListener("submit",async l=>{var w,k,T,I;l.preventDefault();for(const y of i)if(y.required)if(y.type==="checkbox"){if(document.querySelectorAll(`input[name="${y.name}"]:checked`).length===0){W(`${y.label} は必須項目です`);return}}else if(y.type==="radio"){if(!document.querySelector(`input[name="${y.name}"]:checked`)){W(`${y.label} は必須項目です`);return}}else{const a=document.querySelector(`[name="${y.name}"]`);if(!a||!a.value.trim()){W(`${y.label} は必須項目です`);return}}const h=document.getElementById("nextBtn");h.disabled=!0,h.textContent="保存中...";const p={};for(const y of i)y.type==="checkbox"?p[y.name]=Array.from(document.querySelectorAll(`input[name="${y.name}"]:checked`)).map(a=>a.value):y.type==="radio"?p[y.name]=((w=document.querySelector(`input[name="${y.name}"]:checked`))==null?void 0:w.value)??"":p[y.name]=(((k=document.querySelector(`[name="${y.name}"]`))==null?void 0:k.value)??"").trim();try{await C(`/api/forms/${e.id}/partial`,{method:"POST",body:JSON.stringify({lineUserId:(T=m.profile)==null?void 0:T.userId,friendId:m.friendId,data:p})})}catch{}if(document.getElementById("form-page-1").hidden=!0,document.getElementById("form-page-2").hidden=!1,window.scrollTo(0,0),!F){const y=document.querySelector(".x-autocomplete-input");y&&(y.disabled=!0);const a=document.querySelector(".x-autocomplete-wrap");if(a){const u=document.createElement("div");u.id="x-loading-overlay",u.innerHTML='<div class="x-loading-spinner"></div><p>X連携データを読み込み中...</p>',u.style.cssText="display:flex;flex-direction:column;align-items:center;gap:12px;padding:24px 0;color:#888;font-size:14px;",(I=a.parentElement)==null||I.insertBefore(u,a)}}}),Z();else{const l=e.fields.map(J).join("");n.innerHTML=`
317      <div class="form-page">
318        <div class="form-header">
319          <h1>${g(e.name).replace(/\\n|\n/g,"<br>")}</h1>
320          ${e.description&&!e.onSubmitWebhookUrl?`<p class="form-description">${g(e.description).replace(/\\n|\n/g,"<br>")}</p>`:""}
321          ${o}
322        </div>
323        <form id="liff-form" class="form-body" novalidate>
324          ${l}
325          <button type="submit" class="submit-btn" id="submitBtn">送信する</button>
326        </form>
327      </div>
328    `,Z()}}async function $e(e,t){var f;const n=document.getElementById("submit-conditions");n&&n.remove();const o=[["reply","リプライ"],["like","いいね"],["repost","リポスト"],["follow","フォロー"]],i=document.createElement("div");i.id="submit-conditions",i.innerHTML='<div class="x-conditions-card" id="condition-card"></div>';const r=document.getElementById("submitBtn");(f=r==null?void 0:r.parentElement)==null||f.insertBefore(i,r);const s=document.getElementById("condition-card");for(const[d,l]of o){const h=e[d];if(h==null)continue;const p=document.createElement("div");p.className="x-condition-row",p.innerHTML=`<div class="x-condition-check checking"><span class="spin">⏳</span></div><span>${l}を確認中...</span>`,s.appendChild(p),await new Promise(w=>setTimeout(w,600)),h?p.innerHTML=`<div class="x-condition-check pass">✓</div><span>${l}</span>`:p.innerHTML=`<div class="x-condition-check fail">✗</div><span>${l}</span>`}await new Promise(d=>setTimeout(d,400));const c=document.createElement("div");c.className="x-conditions-summary pass",c.textContent="🎉 条件クリア!",i.appendChild(c)}function Ie(e){var o;const t=E(),n=e.split(`
329`).map(i=>`<p>${g(i)}</p>`).join("");t.innerHTML=`
330    <div class="form-page">
331      <div class="success-card">
332        <div class="success-icon">🎉</div>
333        <h2>おめでとうございます!</h2>
334        <div class="success-message">${n}</div>
335        <button class="close-btn" id="closeBtn">閉じる</button>
336      </div>
337    </div>
338  `,(o=document.getElementById("closeBtn"))==null||o.addEventListener("click",()=>{liff.isInClient()?liff.closeWindow():window.close()})}function Se(){var t;const e=E();e.innerHTML=`
339    <div class="form-page">
340      <div class="success-card">
341        <div class="success-icon">✓</div>
342        <h2>送信完了!</h2>
343        <p class="success-message">ご回答ありがとうございました。</p>
344        <button class="close-btn" id="closeBtn">閉じる</button>
345      </div>
346    </div>
347  `,(t=document.getElementById("closeBtn"))==null||t.addEventListener("click",()=>{liff.isInClient()?liff.closeWindow():window.close()}),liff.isInClient()&&setTimeout(()=>{try{liff.closeWindow()}catch{}},3e3)}function U(e){const t=E();t.innerHTML=`
348    <div class="form-page">
349      <div class="card">
350        <h2 style="color: #e53e3e;">エラー</h2>
351        <p class="error">${g(e)}</p>
352      </div>
353    </div>
354  `}function W(e){var i;const t=E().querySelector(".form-error-msg");t&&t.remove();const n=document.createElement("p");n.className="form-error-msg",n.style.cssText="color:#e53e3e;font-size:14px;margin:8px 0;text-align:center;",n.textContent=e;const o=document.getElementById("nextBtn")||document.getElementById("submitBtn");(i=o==null?void 0:o.parentElement)==null||i.insertBefore(n,o)}function Ee(){const e=E();e.innerHTML=`
355    <div class="form-page">
356      <div class="card" style="text-align:center;padding:40px 20px;">
357        <div class="loading-spinner"></div>
358        <p style="margin-top:12px;color:#718096;">読み込み中...</p>
359      </div>
360    </div>
361  `}function Te(){const{formDef:e}=m;if(!e)return{};const t={};for(const n of e.fields)if(n.type==="checkbox"){const o=Array.from(document.querySelectorAll(`input[name="${n.name}"]:checked`)).map(i=>i.value);t[n.name]=o}else if(n.type==="radio"){const o=document.querySelector(`input[name="${n.name}"]:checked`);t[n.name]=(o==null?void 0:o.value)??""}else{const o=document.querySelector(`[name="${n.name}"]`);t[n.name]=(o==null?void 0:o.value)??""}return t}function Le(){const{formDef:e}=m;if(!e)return null;for(const t of e.fields)if(t.required)if(t.type==="checkbox"){if(document.querySelectorAll(`input[name="${t.name}"]:checked`).length===0)return`${t.label} は必須項目です`}else if(t.type==="radio"){if(!document.querySelector(`input[name="${t.name}"]:checked`))return`${t.label} は必須項目です`}else{const n=document.querySelector(`[name="${t.name}"]`);if(!n||!n.value.trim())return`${t.label} は必須項目です`}return null}async function De(){var n,o,i,r,s,c;if(m.submitting||!m.formDef)return;const e=Le();if(e){const f=E().querySelector(".form-error-msg");f&&f.remove();const d=document.createElement("p");d.className="form-error-msg",d.style.cssText="color:#e53e3e;font-size:14px;margin:8px 0;text-align:center;",d.textContent=e;const l=document.getElementById("submitBtn");(n=l==null?void 0:l.parentElement)==null||n.insertBefore(d,l);return}m.submitting=!0;const t=document.getElementById("submitBtn");t&&(t.disabled=!0,t.textContent="送信中...");try{const f=Te();if(console.log("Form data collected:",JSON.stringify(f)),m.formDef.onSubmitWebhookUrl){const h=(f.x_username??"").trim().replace(/^@/,"");if(!h||h!==m.verifiedXUsername){m.submitting=!1,t&&(t.disabled=!1,t.textContent="送信する");const a=E().querySelector(".form-error-msg");a&&a.remove();const u=document.createElement("p");u.className="form-error-msg",u.style.cssText="color:#e53e3e;font-size:14px;margin:8px 0;text-align:center;",u.textContent=h?"X IDを入力後、入力欄の外をタップして確認してください":"X IDを入力してください",(o=t==null?void 0:t.parentElement)==null||o.insertBefore(u,t);return}const p={reply:!0,like:!0,repost:!0,follow:!0};t&&(t.textContent="判定中..."),await $e(p,!0),await new Promise(a=>setTimeout(a,500));const w=m.formDef.onSubmitMessageContent||"条件をクリアしました!",k=w.trimStart().startsWith("{")?"特典をLINEでお送りしました!":w,T={data:{...f},_skipWebhook:!0};(i=m.profile)!=null&&i.userId&&(T.lineUserId=m.profile.userId),m.refTrackedLinkId&&(T.trackedLinkId=m.refTrackedLinkId);const I=await C(`/api/forms/${m.formDef.id}/submit`,{method:"POST",body:JSON.stringify(T)});if(!I.ok){const a=await I.text().catch(()=>"");let u="送信に失敗しました";try{u=JSON.parse(a).error||u}catch{u=a||u}throw new Error(`${I.status}: ${u}`)}const y=await I.clone().json().catch(()=>null);if(((r=y==null?void 0:y.data)==null?void 0:r.webhookPassed)===!1)throw new Error(m.formDef.onSubmitWebhookFailMessage||"条件を満たしていません");Ie(k);return}const d={data:f};(s=m.profile)!=null&&s.userId&&(d.lineUserId=m.profile.userId),m.refTrackedLinkId&&(d.trackedLinkId=m.refTrackedLinkId),console.log("Submitting to:",`/api/forms/${m.formDef.id}/submit`);const l=await C(`/api/forms/${m.formDef.id}/submit`,{method:"POST",body:JSON.stringify(d)});if(console.log("Response status:",l.status),!l.ok){const h=await l.text().catch(()=>"");let p="送信に失敗しました";try{p=JSON.parse(h).error||p}catch{p=h||p}throw new Error(`${l.status}: ${p}`)}Se()}catch(f){m.submitting=!1,t&&(t.disabled=!1,t.textContent="送信する");const d=E().querySelector(".form-error-msg");d&&d.remove();const l=document.createElement("p");l.className="form-error-msg",l.style.cssText="color:#e53e3e;font-size:14px;margin:8px 0;text-align:center;",l.textContent=f instanceof Error?f.message:"送信に失敗しました";const h=document.getElementById("submitBtn");(c=h==null?void 0:h.parentElement)==null||c.insertBefore(l,h)}}function Pe(){const e=document.querySelector(".x-autocomplete-input");if(!e)return;const t=document.getElementById("x-suggest-list"),n=document.getElementById("x-suggest-hint"),o=document.getElementById("x-conditions"),i=document.getElementById("x-conditions-result");if(!t)return;let r=null,s=-1,c=[];function f(){var $;const u=new URLSearchParams(window.location.search).get("gate");if(u)return u;const v=((($=m.formDef)==null?void 0:$.onSubmitWebhookUrl)??"").match(/engagement-gates\/([^/]+)\/verify/);return v?v[1]:null}function d(){var u;const a={};if((u=m.formDef)!=null&&u.onSubmitWebhookHeaders)try{Object.assign(a,JSON.parse(m.formDef.onSubmitWebhookHeaders))}catch{}return a}const l=f();m.xHarnessBaseUrl&&l?fetch(`${m.xHarnessBaseUrl}/api/engagement-gates/${encodeURIComponent(l)}/repliers`,{headers:d()}).then(a=>a.json()).then(a=>{c=a.data??[],F=!0;const u=document.getElementById("x-loading-overlay");u&&(u.remove(),e.disabled=!1,e.focus())}).catch(()=>{F=!0;const a=document.getElementById("x-loading-overlay");a&&(a.remove(),e.disabled=!1)}):F=!0;function h(){o&&(o.hidden=!0),i&&(i.hidden=!0)}function p(){t.hidden=!0,t.innerHTML="",s=-1,n&&(n.hidden=!0)}function w(a){e.value=a,m.verifiedXUsername=a,p(),e.focus(),I(a)}function k(a){a.forEach((x,v)=>{x.classList.toggle("focused",v===s)});const u=a[s];u==null||u.scrollIntoView({block:"nearest"})}function T(a){if(!o||!i)return;if(a.userNotFound){o.hidden=!0,i.innerHTML='❌ Xアカウントが見つかりません<br><span style="font-size:11px;font-weight:normal">IDを確認してもう一度お試しください</span>',i.className="x-conditions-summary fail",i.hidden=!1;return}const u=[{key:"reply",label:"リプライ"},{key:"like",label:"いいね"},{key:"repost",label:"リポスト"},{key:"follow",label:"フォロー"}],x=a.conditions??[],v={};for(const L of x)v[L.type]=L;let $="";for(const L of u){const D=v[L.key];D&&(D.required?D.passed?$+=`
362          <div class="x-condition-row">
363            <div class="x-condition-check pass">✓</div>
364            <span>${g(L.label)}</span>
365          </div>`:$+=`
366          <div class="x-condition-row">
367            <div class="x-condition-check fail">✗</div>
368            <span>${g(L.label)}</span>
369          </div>`:$+=`
370          <div class="x-condition-row">
371            <div class="x-condition-check na">—</div>
372            <span>${g(L.label)}</span>
373          </div>`)}$?(o.innerHTML=`<div class="x-conditions-card">${$}</div>`,o.hidden=!1):o.hidden=!0,a.eligible?(i.textContent="🎉 条件クリア!特典を受け取れます",i.className="x-conditions-summary pass"):(i.textContent="条件を満たしていません",i.className="x-conditions-summary fail"),i.hidden=!1}async function I(a){const u=a.trim().replace(/^@/,"");if(!m.xHarnessBaseUrl||!u)return;const x=f();if(x)try{const v=`${m.xHarnessBaseUrl}/api/engagement-gates/${encodeURIComponent(x)}/verify?username=${encodeURIComponent(u)}`,$=await fetch(v,{headers:d()});if(!$.ok)throw new Error("verify failed");const D=(await $.json()).data;D&&(T(D),D.userNotFound||(m.verifiedXUsername=u,e&&(e.value=u)))}catch{i&&(i.innerHTML='⚠️ 確認中にエラーが発生しました<br><span style="font-size:11px;font-weight:normal">しばらく待ってからもう一度お試しください</span>',i.className="x-conditions-summary fail",i.hidden=!1)}}function y(a){if(t.innerHTML="",s=-1,a.length===0){t.hidden=!0,n&&(n.innerHTML=c.length===0?'<span style="color:#e53e3e">⏳ まだリアクションがありません</span><br><span style="font-size:11px;color:#888">ポストにリポスト&フォローしてから再度お試しください</span>':'<span style="color:#888">候補に表示されなくても、そのままIDを入力して送信できます</span>',n.hidden=!1);return}n&&(n.hidden=!0);for(const u of a){const x=document.createElement("li");x.className="x-suggest-item",x.dataset.username=u.username;const v=u.profileImageUrl?`<img class="x-suggest-avatar" src="${g(u.profileImageUrl)}" alt="" />`:'<div class="x-suggest-avatar-placeholder">@</div>';x.innerHTML=`
374        ${v}
375        <div class="x-suggest-names">
376          <span class="x-suggest-display">${g(u.displayName)}</span>
377          <span class="x-suggest-username">@${g(u.username)}</span>
378        </div>
379      `,x.addEventListener("mousedown",$=>{$.preventDefault(),w(u.username)}),t.appendChild(x)}t.hidden=!1}e.addEventListener("input",()=>{const a=e.value.trim().replace(/^@/,"");if(r!==null&&clearTimeout(r),a!==m.verifiedXUsername&&(m.verifiedXUsername=""),!a){p(),h();return}if(a.length<3){p(),h(),n&&(n.textContent="3文字以上入力してください",n.hidden=!1);return}n&&(n.hidden=!0);const u=a.toLowerCase(),x=c.filter(v=>v.username.toLowerCase().includes(u)||v.displayName.toLowerCase().includes(u)).slice(0,5);y(x)}),e.addEventListener("keydown",a=>{const u=t.querySelectorAll(".x-suggest-item");if(u.length)if(a.key==="ArrowDown")a.preventDefault(),s=Math.min(s+1,u.length-1),k(u);else if(a.key==="ArrowUp")a.preventDefault(),s=Math.max(s-1,0),k(u);else if(a.key==="Enter"&&s>=0){a.preventDefault();const v=u[s].dataset.username;v&&w(v)}else a.key==="Escape"&&p()}),e.addEventListener("blur",()=>{setTimeout(()=>{p();const a=e.value.trim().replace(/^@/,"");a&&f()&&(r!==null&&clearTimeout(r),r=setTimeout(()=>{I(a)},300))},150)})}function Z(){const e=document.getElementById("liff-form");e==null||e.addEventListener("submit",t=>{t.preventDefault(),De()}),Pe()}async function Ue(e){var t;if(!e){U("フォームIDが指定されていません");return}Ee();try{const[n,o]=await Promise.all([liff.getProfile(),C(`/api/forms/${e}`)]);m.profile=n;try{m.friendId=localStorage.getItem(Q)}catch{}const i=liff.getIDToken();if(i&&C("/api/liff/link",{method:"POST",body:JSON.stringify({idToken:i,displayName:n.displayName,existingUuid:m.friendId})}).then(async d=>{var l;if(d.ok){const h=await d.json();if((l=h==null?void 0:h.data)!=null&&l.userId)try{localStorage.setItem(Q,h.data.userId),m.friendId=h.data.userId}catch{}}}).catch(()=>{}),!o.ok){o.status===404?U("フォームが見つかりません"):U("フォームの読み込みに失敗しました");return}const r=await o.json();if(!r.success||!r.data){U("フォームの読み込みに失敗しました");return}if(!r.data.isActive){U("このフォームは現在受付を停止しています");return}m.formDef=r.data;const s=new URLSearchParams(window.location.search),c=s.get("xh");if(c)m.xHarnessBaseUrl=c.replace(/\/$/,"");else if(r.data.onSubmitWebhookUrl){const d=r.data.onSubmitWebhookUrl.match(/^(https?:\/\/[^/]+)/);d&&(m.xHarnessBaseUrl=d[1])}const f=s.get("ref");f&&(m.refTrackedLinkId=f),ke(),C(`/api/forms/${m.formDef.id}/opened`,{method:"POST",body:JSON.stringify({lineUserId:(t=m.profile)==null?void 0:t.userId,friendId:m.friendId})}).catch(()=>{})}catch(n){U(n instanceof Error?n.message:"エラーが発生しました")}}function Be(){const e=new URLSearchParams(window.location.search).get("liffId");return e||"2009652523-KnDvMP2A"}const H=Be();if(!H)throw new Error("LIFF ID not found. Set ?liffId= in LIFF endpoint URL or VITE_LIFF_ID env.");const ie="lh_uuid";let A="";function S(e,t){return fetch(e,{...t,headers:{"Content-Type":"application/json",...t==null?void 0:t.headers}})}function Ce(){return window.location.pathname.replace(/^\/+/,"")==="book"?"book":new URLSearchParams(window.location.search).get("page")}function Ne(){return new URLSearchParams(window.location.search).get("redirect")}function R(){return new URLSearchParams(window.location.search).get("ref")}function z(){try{return localStorage.getItem(ie)}catch{return null}}function V(e){try{localStorage.setItem(ie,e)}catch{}}function j(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function G(e){const t=document.getElementById("app"),n=A?`https://line.me/R/ti/p/${A}`:"#";t.innerHTML=`
380    <div class="card">
381      <div class="profile">
382        ${e.pictureUrl?`<img src="${e.pictureUrl}" alt="" />`:""}
383        <p class="name">${j(e.displayName)} さん</p>
384      </div>
385      <p class="message">まずは友だち追加をお願いします</p>
386      <a href="${n}" class="add-friend-btn" id="addFriendBtn">
387        友だち追加して始める
388      </a>
389      <p class="sub-message">追加後、この画面に戻ってきてください</p>
390    </div>
391  `;let o=!1;const i=async()=>
391{if(document.visibilityState==="visible")try{const{friendFlag:r}=await liff.getFriendship();if(!r)return;try{const c=liff.getIDToken();c&&await S("/api/liff/link",{method:"POST",body:JSON.stringify({idToken:c,displayName:e.displayName,existingUuid:z(),ref})})}catch{}const s=new URLSearchParams(window.location.search).get("form");if(s&&!o){o=!0;try{const c=await liff.getProfile(),f=liff.getIDToken(),d=new URLSearchParams(window.location.search);await S("/api/liff/send-form-link",{method:"POST",body:JSON.stringify({lineUserId:c.userId,formId:s,idToken:f||"",ref:d.get("ref")||"",gate:d.get("gate")||"",xh:d.get("xh")||"",ig:d.get("ig")||""})})}catch{}}document.removeEventListener("visibilitychange",i),X(e,!1)}catch{}};document.addEventListener("visibilitychange",i)}function X(e,t){const n=document.getElementById("app"),o=R();n.innerHTML=`
392    <div class="card">
393      <div class="check-icon">${t?"🔄":"✓"}</div>
394      <h2>${t?"おかえりなさい!":"登録完了!"}</h2>
395      <div class="profile">
396        ${e.pictureUrl?`<img src="${e.pictureUrl}" alt="" />`:""}
397        <p class="name">${j(e.displayName)} さん</p>
398      </div>
399      <p class="message">
400        ${t?"以前のアカウント情報を引き継ぎました。":"ありがとうございます!これからお役立ち情報をお届けします。"}
401        <br>
401このページは閉じて大丈夫です。
402      </p>
403      ${o?`<p class="ref-badge">${j(o)}</p>`:""}
404    </div>
405  `,A&&setTimeout(()=>{window.location.href=`https://line.me/R/oaMessage/${A}/`},2e3)}function P(e){const t=document.getElementById("app");t.innerHTML=`
406    <div class="card">
407      <h2>エラー</h2>
408      <p class="error">${j(e)}</p>
409    </div>
410  `}async function ee(){const e=Ne(),t=R();try{const n=z(),[o,i,r]=await Promise.all([liff.getProfile(),Promise.resolve(liff.getIDToken()),liff.getFriendship()]),s=new URLSearchParams(window.location.search),c=S("/api/liff/link",{method:"POST",body:JSON.stringify({idToken:i,displayName:o.displayName,existingUuid:n,ref:t,ig:s.get("ig")||""})}).then(async f=>{var d;if(f.ok){const l=await f.json();(d=l==null?void 0:l.data)!=null&&d.userId&&V(l.data.userId)}return f}).catch(()=>{});if(t&&S("/api/affiliates/click",{method:"POST",body:JSON.stringify({code:t,url:window.location.href})}).catch(()=>{}),t&&!r.friendFlag){const f=liff.getIDToken();f&&S("/api/liff/preregister",{method:"POST",body:JSON.stringify({idToken:f,ref:t,displayName:o.displayName})}).catch(()=>{})}if(e){if(await Promise.race([c,new Promise(f=>setTimeout(f,500))]),e.includes("/t/")){const f=e.includes("?")?"&":"?";window.location.href=`${e}${f}lu=${encodeURIComponent(o.userId)}`}else window.location.href=e;return}if(await c,!r.friendFlag)G(o);else{const f=new URLSearchParams(window.location.search).get("form");if(f){try{const d=liff.getIDToken(),l=new URLSearchParams(window.location.search);await S("/api/liff/send-form-link",{method:"POST",body:JSON.stringify({lineUserId:o.userId,formId:f,idToken:d||"",ref:t||"",gate:l.get("gate")||"",xh:l.get("xh")||"",ig:l.get("ig")||""})})}catch{}X(o,!!n)}else X(o,!!n)}}catch(n){e?window.location.href=e:P(n instanceof Error?n.message:"エラーが発生しました")}}async function Oe(){const[e,t,n]=await Promise.all([liff.getProfile(),Promise.resolve(liff.getIDToken()),liff.getFriendship()]);if(!t){P("LINE 認証情報の取得に失敗しました。LINE アプリ内で再度開いてください。");return}const o=z(),i=R(),r=new URLSearchParams(window.location.search).get("ig");if(S("/api/liff/link",{method:"POST",body:JSON.stringify({idToken:t,displayName:e.displayName,existingUuid:o,ref:i||void 0,ig:r||void 0})}).then(async f=>{var d;if(f.ok){const l=await f.json();(d=l==null?void 0:l.data)!=null&&d.userId&&V(l.data.userId)}}).catch(()=>{}),i&&S("/api/affiliates/click",{method:"POST",body:JSON.stringify({code:i,url:window.location.href})}).catch(()=>{}),!n.friendFlag){G(e);return}const s=document.getElementById("app");if(!s){P("mount target #app が見つかりません");return}const{mountSalonBooking:c}=await ne(async()=>{const{mountSalonBooking:f}=await import("./main-B-S1uEee.js");return{mountSalonBooking:f}},__vite__mapDeps([0,1,2]));c(s,{liffId:H,lineUserId:e.userId,idToken:t})}async function te(e){const[t,n,o]=await Promise.all([liff.getProfile(),Promise.resolve(liff.getIDToken()),liff.getFriendship()]);if(!n){P("LINE 認証情報の取得に失敗しました。LINE アプリ内で再度開いてください。");return}const i=z(),r=R();if(S("/api/liff/link",{method:"POST",body:JSON.stringify({idToken:n,displayName:t.displayName,existingUuid:i,ref:r||void 0})}).then(async p=>{var w;if(p.ok){const k=await p.json();(w=k==null?void 0:k.data)!=null&&w.userId&&V(k.data.userId)}}).catch(()=>{}),!o.friendFlag){G(t);return}const s=document.getElementById("app");if(!s){P("mount target #app が見つかりません");return}const f=new URLSearchParams(window.location.search).get("id")??"";if(e==="detail"&&!f){P("id クエリパラメータが必要です(?page=event&id=<eventId>)");return}const{mountEventBooking:d}=await ne(async()=>{const{mountEventBooking:p}=await import("./main-Kg_lE8TC.js");return{mountEventBooking:p}},__vite__mapDeps([3,1,4])),l={liffId:H,lineUserId:t.userId,idToken:n};d(s,l,e==="detail"?{kind:"detail",eventId:f}:{kind:"history"})}async function Me(){var e;try{if(await liff.init({liffId:H}),!liff.isLoggedIn()){liff.login({redirectUri:window.location.href});return}try{const o=await(await fetch(`/api/liff/config?liffId=${encodeURIComponent(H)}`)).json();o.success&&((e=o.data)!=null&&e.botBasicId)&&(A=o.data.botBasicId)}catch{}const t=Ce();if(t==="book")await ve();else if(t==="salon-book")await Oe();else if(t==="event")await te("detail");else if(t==="event-me")await te("history");else if(t==="form"){const o=new URLSearchParams(window.location.search).get("id");await Ue(o)}else t?await ee():await ee()}catch(t){P(t instanceof Error?t.message:"LIFF初期化エラー")}}Me();

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.