// submit.js — contribute-a-part flow: AI auto-fill from datasheet + submission to Corben functions. const API = 'https://api.corben.world'; const FN_AUTOFILL = 'd4f34d9c-6e8f-4328-89a2-b3c3b79017db'; const TK_AUTOFILL = '3f5dc4a97de91e7e9117b9a12a3061f6'; const FN_SUBMIT = 'b02d634b-cd6d-414d-bf9c-80cf6cc2ccdc'; const TK_SUBMIT = '9c3ed2ece766bcc18ed7d33996bfeb86'; const $ = (id) => document.getElementById(id); async function invoke(fn, token, payload) { const r = await fetch(`${API}/functions/${fn}/invoke?token=${token}`, { method: 'POST', headers: window.ppcbAuth(), body: JSON.stringify(payload) }); // authed: sends the session token return r.json(); } $('autofill').onclick = async (e) => { e.preventDefault(); const mpn = $('mpn').value.trim(); if (!mpn && !$('description').value.trim()) { $('af-status').textContent = 'Enter an MPN or paste datasheet text first.'; return; } $('autofill').disabled = true; $('af-status').innerHTML = ' drafting from datasheet…'; try { const d = await invoke(FN_AUTOFILL, TK_AUTOFILL, { mpn, class: $('class').value, description: $('description').value.trim() }); if (!d.ok) throw new Error(d.error || 'autofill failed'); const s = d.suggested; if (s.summary) $('summary').value = s.summary; if (s.when_to_use) $('when_to_use').value = s.when_to_use; if (s.use_cases) $('use_cases').value = s.use_cases.join('\n'); if (s.params) $('params').value = s.params.map((p) => `${p.name}: ${p.value}${p.unit ? ' ' + p.unit : ''}`).join('\n'); if (s.spice_model) $('spice').value = s.spice_model; const t = s.requirements_tags || {}; if (t.package && !$('package').value) $('package').value = t.package; if (t.class && !$('class').value) $('class').value = t.class; $('af-status').innerHTML = '✓ drafted — review every field before submitting.'; } catch (err) { $('af-status').textContent = '⚠ ' + err.message; } $('autofill').disabled = false; }; $('model3d').onchange = () => { const f = $('model3d').files[0]; if (f) $('drop-label').textContent = '✓ ' + f.name; }; $('submit').onclick = async () => { const parseParams = (t) => t.split('\n').map((l) => l.trim()).filter(Boolean).map((l) => { const [n, ...rest] = l.split(':'); const v = rest.join(':').trim(); const m = v.match(/^([\d.\-+/]+)\s*(.*)$/); return { name: n.trim(), value: m ? m[1] : v, unit: m ? m[2] : '' }; }); const part = { mpn: $('mpn').value.trim(), name: $('mpn').value.trim(), class: $('class').value, manufacturer: $('manufacturer').value.trim(), package: $('package').value.trim(), datasheet_url: $('datasheet_url').value.trim(), summary: $('summary').value.trim(), when_to_use: $('when_to_use').value.trim(), use_cases: $('use_cases').value.split('\n').map((l) => l.trim()).filter(Boolean), params: parseParams($('params').value), spice: $('spice').value.trim(), model_3d_name: $('model3d').files[0] ? $('model3d').files[0].name : '', }; const email = $('email').value.trim(); $('submit').disabled = true; $('sub-status').innerHTML = ' submitting…'; try { const d = await invoke(FN_SUBMIT, TK_SUBMIT, { email, part }); if (!d.ok) throw new Error(d.error || 'submit failed'); document.querySelector('.form').innerHTML = `

Thank you — submitted for review ✓

Browse the catalog →`; } catch (err) { $('sub-status').textContent = '⚠ ' + err.message; $('submit').disabled = false; } };