| |
|
| |
|
| |
|
| | document.addEventListener('DOMContentLoaded', function() {
|
| | console.log('✅ Shop11 API Functions loaded');
|
| |
|
| |
|
| | 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>';
|
| |
|
| |
|
| | if (window.saveApiLogToSupabase) {
|
| | saveApiLogToSupabase(
|
| | '地金チェック削除',
|
| | '/api/shouhin/gold_check_id_delete',
|
| | requestData,
|
| | data,
|
| | 'success'
|
| | );
|
| | }
|
| | })
|
| | .catch(err => {
|
| | resultDiv.innerHTML = '<span style="color:red;">エラー: ' + err.message + '</span>';
|
| |
|
| |
|
| | 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');
|
| | }
|
| | });
|
| | }
|
| |
|