Spaces:
Sleeping
Sleeping
| // Shop11 API Functions | |
| // ページビルダーで作成したページで使用するAPI呼び出し関数 | |
| document.addEventListener('DOMContentLoaded', function() { | |
| console.log('✅ Shop11 API Functions loaded'); | |
| // すべてのAPIボタンにイベントリスナーを追加 | |
| document.addEventListener('click', function(e) { | |
| const action = e.target.getAttribute('data-action'); | |
| if (!action) return; | |
| switch(action) { | |
| case 'goldCheckDelete': | |
| goldCheckDelete(e.target); | |
| break; | |
| case 'createSateiTitle': | |
| createSateiTitle(e.target); | |
| break; | |
| case 'sendNotification': | |
| sendNotification(e.target); | |
| break; | |
| case 'searchProduct': | |
| searchProduct(e.target); | |
| break; | |
| case 'loadProductTable': | |
| loadProductTable(e.target); | |
| break; | |
| case 'clearProductTable': | |
| clearProductTable(e.target); | |
| break; | |
| case 'loadCustomerTable': | |
| loadCustomerTable(e.target); | |
| break; | |
| case 'clearCustomerTable': | |
| clearCustomerTable(e.target); | |
| break; | |
| case 'loadSateiTable': | |
| loadSateiTable(e.target); | |
| break; | |
| case 'clearSateiTable': | |
| clearSateiTable(e.target); | |
| break; | |
| case 'registerProduct': | |
| registerProduct(e.target); | |
| break; | |
| } | |
| }); | |
| }); | |
| // 地金チェック削除 | |
| function goldCheckDelete(button) { | |
| const block = button.closest('.shop11-api-block'); | |
| const productId = block.querySelector('.gold-product-id').value; | |
| const resultDiv = block.querySelector('.gold-check-result'); | |
| if (!productId) { | |
| alert('商品IDを入力してください'); | |
| return; | |
| } | |
| resultDiv.style.display = 'block'; | |
| resultDiv.innerHTML = '処理中...'; | |
| const requestData = { product_id: productId }; | |
| fetch('/api/shouhin/gold_check_id_delete', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content || '' | |
| }, | |
| body: JSON.stringify(requestData) | |
| }) | |
| .then(res => res.json()) | |
| .then(data => { | |
| resultDiv.innerHTML = '<pre>' + JSON.stringify(data, null, 2) + '</pre>'; | |
| // Supabaseにログ保存 | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase( | |
| '地金チェック削除', | |
| '/api/shouhin/gold_check_id_delete', | |
| requestData, | |
| data, | |
| 'success' | |
| ); | |
| } | |
| }) | |
| .catch(err => { | |
| resultDiv.innerHTML = '<span style="color:red;">エラー: ' + err.message + '</span>'; | |
| // Supabaseにエラーログ保存 | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase( | |
| '地金チェック削除', | |
| '/api/shouhin/gold_check_id_delete', | |
| requestData, | |
| { error: err.message }, | |
| 'error' | |
| ); | |
| } | |
| }); | |
| } | |
| // 査定タイトル生成 | |
| function createSateiTitle(button) { | |
| const block = button.closest('.shop11-api-block'); | |
| const productId = block.querySelector('.satei-product-id').value; | |
| const resultDiv = block.querySelector('.satei-title-result'); | |
| if (!productId) { | |
| alert('商品IDを入力してください'); | |
| return; | |
| } | |
| resultDiv.style.display = 'block'; | |
| resultDiv.innerHTML = '生成中...'; | |
| const endpoint = '/api/satei_func/create_title/' + productId; | |
| const requestData = { product_id: productId }; | |
| fetch(endpoint, { | |
| method: 'GET', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| } | |
| }) | |
| .then(res => res.json()) | |
| .then(data => { | |
| resultDiv.innerHTML = '<strong>タイトル:</strong><br>' + (data.title || JSON.stringify(data, null, 2)); | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('査定タイトル生成', endpoint, requestData, data, 'success'); | |
| } | |
| }) | |
| .catch(err => { | |
| resultDiv.innerHTML = '<span style="color:red;">エラー: ' + err.message + '</span>'; | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('査定タイトル生成', endpoint, requestData, { error: err.message }, 'error'); | |
| } | |
| }); | |
| } | |
| // メール送信 | |
| function sendNotification(button) { | |
| const block = button.closest('.shop11-api-block'); | |
| const to = block.querySelector('.mail-to').value; | |
| const subject = block.querySelector('.mail-subject').value; | |
| const body = block.querySelector('.mail-body').value; | |
| const resultDiv = block.querySelector('.mail-result'); | |
| if (!to || !subject || !body) { | |
| alert('すべての項目を入力してください'); | |
| return; | |
| } | |
| resultDiv.style.display = 'block'; | |
| resultDiv.innerHTML = '送信中...'; | |
| const endpoint = '/api/notification/mail'; | |
| const requestData = { to, subject, body }; | |
| fetch(endpoint, { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content || '' | |
| }, | |
| body: JSON.stringify(requestData) | |
| }) | |
| .then(res => res.json()) | |
| .then(data => { | |
| resultDiv.innerHTML = '<span style="color:green;">✅ 送信完了</span><br><pre>' + JSON.stringify(data, null, 2) + '</pre>'; | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('メール送信', endpoint, requestData, data, 'success'); | |
| } | |
| }) | |
| .catch(err => { | |
| resultDiv.innerHTML = '<span style="color:red;">❌ エラー: ' + err.message + '</span>'; | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('メール送信', endpoint, requestData, { error: err.message }, 'error'); | |
| } | |
| }); | |
| } | |
| // 商品検索 | |
| function searchProduct(button) { | |
| const block = button.closest('.shop11-api-block'); | |
| const keyword = block.querySelector('.search-keyword').value; | |
| const resultDiv = block.querySelector('.search-result'); | |
| if (!keyword) { | |
| alert('検索キーワードを入力してください'); | |
| return; | |
| } | |
| resultDiv.style.display = 'block'; | |
| resultDiv.innerHTML = '検索中...'; | |
| const endpoint = '/api/auto_complete_refasta/ResultSearch?q=' + encodeURIComponent(keyword); | |
| const requestData = { keyword }; | |
| fetch(endpoint, { | |
| method: 'GET', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| } | |
| }) | |
| .then(res => res.json()) | |
| .then(data => { | |
| if (Array.isArray(data) && data.length > 0) { | |
| let html = '<ul style="list-style:none; padding:0;">'; | |
| data.forEach(item => { | |
| html += '<li style="padding:10px; border-bottom:1px solid #eee;">' + | |
| (item.label || item.name || JSON.stringify(item)) + '</li>'; | |
| }); | |
| html += '</ul>'; | |
| resultDiv.innerHTML = html; | |
| } else { | |
| resultDiv.innerHTML = '検索結果なし'; | |
| } | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('商品検索', endpoint, requestData, data, 'success'); | |
| } | |
| }) | |
| .catch(err => { | |
| resultDiv.innerHTML = '<span style="color:red;">エラー: ' + err.message + '</span>'; | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('商品検索', endpoint, requestData, { error: err.message }, 'error'); | |
| } | |
| }); | |
| } | |
| // 商品データテーブル読込 | |
| function loadProductTable(button) { | |
| const block = button.closest('.shop11-api-block'); | |
| const keyword = block.querySelector('.product-search-keyword').value; | |
| const tableBody = block.querySelector('.product-table-body'); | |
| const infoDiv = block.querySelector('.product-table-info'); | |
| if (!keyword) { | |
| alert('検索キーワードを入力してください'); | |
| return; | |
| } | |
| tableBody.innerHTML = '<tr><td colspan="7" class="text-center">🔍 検索中...</td></tr>'; | |
| const endpoint = '/api/auto_complete_refasta/ResultSearch?q=' + encodeURIComponent(keyword); | |
| const requestData = { keyword }; | |
| fetch(endpoint, { | |
| method: 'GET', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| } | |
| }) | |
| .then(res => res.json()) | |
| .then(data => { | |
| if (Array.isArray(data) && data.length > 0) { | |
| let html = ''; | |
| data.forEach((item, index) => { | |
| html += '<tr>'; | |
| html += '<td>' + (item.product_id || item.id || index + 1) + '</td>'; | |
| html += '<td>' + (item.label || item.name || item.title || '-') + '</td>'; | |
| html += '<td>' + (item.brand || item.maker || '-') + '</td>'; | |
| html += '<td>' + (item.category || item.category_name || '-') + '</td>'; | |
| html += '<td class="text-right">' + (item.price ? '¥' + parseInt(item.price).toLocaleString() : '-') + '</td>'; | |
| html += '<td>' + getStatusBadge(item.status) + '</td>'; | |
| html += '<td>' + | |
| '<button class="btn btn-sm btn-info mr-1" onclick="alert(\'商品ID: ' + (item.product_id || item.id) + '\')">📝 詳細</button>' + | |
| '<button class="btn btn-sm btn-warning" onclick="alert(\'編集機能は準備中です\')">✏️ 編集</button>' + | |
| '</td>'; | |
| html += '</tr>'; | |
| }); | |
| tableBody.innerHTML = html; | |
| infoDiv.innerHTML = '<small>✅ ' + data.length + '件の商品が見つかりました</small>'; | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('商品データテーブル読込', endpoint, requestData, { count: data.length }, 'success'); | |
| } | |
| } else { | |
| tableBody.innerHTML = '<tr><td colspan="7" class="text-center text-muted">📭 検索結果なし</td></tr>'; | |
| infoDiv.innerHTML = '<small>検索結果: 0件</small>'; | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('商品データテーブル読込', endpoint, requestData, { count: 0 }, 'success'); | |
| } | |
| } | |
| }) | |
| .catch(err => { | |
| tableBody.innerHTML = '<tr><td colspan="7" class="text-center text-danger">❌ エラー: ' + err.message + '</td></tr>'; | |
| infoDiv.innerHTML = '<small class="text-danger">データ読込エラー</small>'; | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('商品データテーブル読込', endpoint, requestData, { error: err.message }, 'error'); | |
| } | |
| }); | |
| } | |
| // 商品テーブルクリア | |
| function clearProductTable(button) { | |
| const block = button.closest('.shop11-api-block'); | |
| const keyword = block.querySelector('.product-search-keyword'); | |
| const tableBody = block.querySelector('.product-table-body'); | |
| const infoDiv = block.querySelector('.product-table-info'); | |
| keyword.value = ''; | |
| tableBody.innerHTML = '<tr><td colspan="7" class="text-center text-muted">検索キーワードを入力して検索してください</td></tr>'; | |
| infoDiv.innerHTML = ''; | |
| } | |
| // ステータスバッジ生成 | |
| function getStatusBadge(status) { | |
| if (!status) return '<span class="badge badge-secondary">-</span>'; | |
| const statusMap = { | |
| '1': { label: '在庫あり', color: 'success' }, | |
| '2': { label: '予約中', color: 'warning' }, | |
| '3': { label: '売約済', color: 'danger' }, | |
| '4': { label: '出品中', color: 'info' }, | |
| '5': { label: '取り下げ', color: 'secondary' } | |
| }; | |
| const statusInfo = statusMap[status] || { label: status, color: 'secondary' }; | |
| return '<span class="badge badge-' + statusInfo.color + '">' + statusInfo.label + '</span>'; | |
| } | |
| // 顧客データテーブル読込 | |
| function loadCustomerTable(button) { | |
| const block = button.closest('.shop11-api-block'); | |
| const keyword = block.querySelector('.customer-search-keyword').value; | |
| const tableBody = block.querySelector('.customer-table-body'); | |
| const infoDiv = block.querySelector('.customer-table-info'); | |
| if (!keyword) { | |
| alert('検索キーワードを入力してください'); | |
| return; | |
| } | |
| tableBody.innerHTML = '<tr><td colspan="7" class="text-center">🔍 検索中...</td></tr>'; | |
| const endpoint = '/api/Eoc/search?keyword=' + encodeURIComponent(keyword); | |
| const requestData = { keyword }; | |
| fetch(endpoint, { | |
| method: 'GET', | |
| headers: { 'Content-Type': 'application/json' } | |
| }) | |
| .then(res => res.json()) | |
| .then(data => { | |
| const customers = Array.isArray(data) ? data : (data.data || []); | |
| if (customers.length > 0) { | |
| let html = ''; | |
| customers.forEach(customer => { | |
| html += '<tr>'; | |
| html += '<td>' + (customer.ecc_id || customer.id || '-') + '</td>'; | |
| html += '<td>' + (customer.name1 || customer.name || '-') + '</td>'; | |
| html += '<td>' + (customer.tel || customer.phone || '-') + '</td>'; | |
| html += '<td>' + (customer.mail1 || customer.email || '-') + '</td>'; | |
| html += '<td>' + (customer.zip1 || customer.zip || '-') + '</td>'; | |
| html += '<td>' + (customer.address1 || customer.address || '-') + '</td>'; | |
| html += '<td>' + | |
| '<button class="btn btn-sm btn-info mr-1" onclick="alert(\'顧客ID: ' + (customer.ecc_id || customer.id) + '\')">📋 詳細</button>' + | |
| '<button class="btn btn-sm btn-primary" onclick="alert(\'編集機能は準備中です\')">✏️ 編集</button>' + | |
| '</td>'; | |
| html += '</tr>'; | |
| }); | |
| tableBody.innerHTML = html; | |
| infoDiv.innerHTML = '<small>✅ ' + customers.length + '件の顧客が見つかりました</small>'; | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('顧客検索テーブル', endpoint, requestData, { count: customers.length }, 'success'); | |
| } | |
| } else { | |
| tableBody.innerHTML = '<tr><td colspan="7" class="text-center text-muted">📭 検索結果なし</td></tr>'; | |
| infoDiv.innerHTML = '<small>検索結果: 0件</small>'; | |
| } | |
| }) | |
| .catch(err => { | |
| tableBody.innerHTML = '<tr><td colspan="7" class="text-center text-danger">❌ エラー: ' + err.message + '</td></tr>'; | |
| infoDiv.innerHTML = '<small class="text-danger">データ読込エラー</small>'; | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('顧客検索テーブル', endpoint, requestData, { error: err.message }, 'error'); | |
| } | |
| }); | |
| } | |
| // 顧客テーブルクリア | |
| function clearCustomerTable(button) { | |
| const block = button.closest('.shop11-api-block'); | |
| block.querySelector('.customer-search-keyword').value = ''; | |
| block.querySelector('.customer-table-body').innerHTML = '<tr><td colspan="7" class="text-center text-muted">検索キーワードを入力して検索してください</td></tr>'; | |
| block.querySelector('.customer-table-info').innerHTML = ''; | |
| } | |
| // 査定データテーブル読込 | |
| function loadSateiTable(button) { | |
| const block = button.closest('.shop11-api-block'); | |
| const keyword = block.querySelector('.satei-search-keyword').value; | |
| const tableBody = block.querySelector('.satei-table-body'); | |
| const infoDiv = block.querySelector('.satei-table-info'); | |
| if (!keyword) { | |
| alert('検索キーワードを入力してください'); | |
| return; | |
| } | |
| tableBody.innerHTML = '<tr><td colspan="7" class="text-center">🔍 検索中...</td></tr>'; | |
| const endpoint = '/api/satei/search?keyword=' + encodeURIComponent(keyword); | |
| const requestData = { keyword }; | |
| fetch(endpoint, { | |
| method: 'GET', | |
| headers: { 'Content-Type': 'application/json' } | |
| }) | |
| .then(res => res.json()) | |
| .then(data => { | |
| const sateiList = Array.isArray(data) ? data : (data.data || []); | |
| if (sateiList.length > 0) { | |
| let html = ''; | |
| sateiList.forEach(satei => { | |
| html += '<tr>'; | |
| html += '<td>' + (satei.id || '-') + '</td>'; | |
| html += '<td>' + (satei.product_name || satei.title || '-') + '</td>'; | |
| html += '<td>' + (satei.customer_name || satei.ecc_name || '-') + '</td>'; | |
| html += '<td class="text-right">' + (satei.price ? '¥' + parseInt(satei.price).toLocaleString() : '-') + '</td>'; | |
| html += '<td>' + (satei.satei_date || satei.created_at || '-') + '</td>'; | |
| html += '<td>' + getSateiStatusBadge(satei.status) + '</td>'; | |
| html += '<td>' + | |
| '<button class="btn btn-sm btn-info mr-1" onclick="alert(\'査定ID: ' + (satei.id) + '\')">📋 詳細</button>' + | |
| '<button class="btn btn-sm btn-warning" onclick="alert(\'編集機能は準備中です\')">✏️ 編集</button>' + | |
| '</td>'; | |
| html += '</tr>'; | |
| }); | |
| tableBody.innerHTML = html; | |
| infoDiv.innerHTML = '<small>✅ ' + sateiList.length + '件の査定が見つかりました</small>'; | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('査定検索テーブル', endpoint, requestData, { count: sateiList.length }, 'success'); | |
| } | |
| } else { | |
| tableBody.innerHTML = '<tr><td colspan="7" class="text-center text-muted">📭 検索結果なし</td></tr>'; | |
| infoDiv.innerHTML = '<small>検索結果: 0件</small>'; | |
| } | |
| }) | |
| .catch(err => { | |
| tableBody.innerHTML = '<tr><td colspan="7" class="text-center text-danger">❌ エラー: ' + err.message + '</td></tr>'; | |
| infoDiv.innerHTML = '<small class="text-danger">データ読込エラー</small>'; | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('査定検索テーブル', endpoint, requestData, { error: err.message }, 'error'); | |
| } | |
| }); | |
| } | |
| // 査定テーブルクリア | |
| function clearSateiTable(button) { | |
| const block = button.closest('.shop11-api-block'); | |
| block.querySelector('.satei-search-keyword').value = ''; | |
| block.querySelector('.satei-table-body').innerHTML = '<tr><td colspan="7" class="text-center text-muted">検索キーワードを入力して検索してください</td></tr>'; | |
| block.querySelector('.satei-table-info').innerHTML = ''; | |
| } | |
| // 査定ステータスバッジ | |
| function getSateiStatusBadge(status) { | |
| const statusMap = { | |
| '1': { label: '査定中', color: 'info' }, | |
| '2': { label: '査定完了', color: 'success' }, | |
| '3': { label: '買取完了', color: 'primary' }, | |
| '4': { label: 'キャンセル', color: 'danger' } | |
| }; | |
| const statusInfo = statusMap[status] || { label: status || '-', color: 'secondary' }; | |
| return '<span class="badge badge-' + statusInfo.color + '">' + statusInfo.label + '</span>'; | |
| } | |
| // 商品登録 | |
| function registerProduct(button) { | |
| const block = button.closest('.shop11-api-block'); | |
| const form = block.querySelector('.product-register-form'); | |
| const resultDiv = block.querySelector('.register-result'); | |
| const name = block.querySelector('.product-name').value; | |
| const brand = block.querySelector('.product-brand').value; | |
| const category = block.querySelector('.product-category').value; | |
| const price = block.querySelector('.product-price').value; | |
| const description = block.querySelector('.product-description').value; | |
| const status = block.querySelector('.product-status').value; | |
| if (!name || !price) { | |
| alert('商品名と価格は必須です'); | |
| return; | |
| } | |
| resultDiv.style.display = 'block'; | |
| resultDiv.innerHTML = '💾 登録中...'; | |
| const endpoint = '/api/shouhin/register'; | |
| const requestData = { | |
| name: name, | |
| brand: brand, | |
| category: category, | |
| price: price, | |
| description: description, | |
| status: status | |
| }; | |
| fetch(endpoint, { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content || '' | |
| }, | |
| body: JSON.stringify(requestData) | |
| }) | |
| .then(res => res.json()) | |
| .then(data => { | |
| resultDiv.innerHTML = '<div class="alert alert-success">✅ 商品を登録しました!<br>商品ID: ' + (data.product_id || data.id || '不明') + '</div>'; | |
| form.reset(); | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('商品登録', endpoint, requestData, data, 'success'); | |
| } | |
| }) | |
| .catch(err => { | |
| resultDiv.innerHTML = '<div class="alert alert-danger">❌ エラー: ' + err.message + '</div>'; | |
| if (window.saveApiLogToSupabase) { | |
| saveApiLogToSupabase('商品登録', endpoint, requestData, { error: err.message }, 'error'); | |
| } | |
| }); | |
| } | |