HOME
Household Inventory Log
var SPEC={"slug":"household-inventory","title":"Household Inventory Log","kicker":"HOME","accent":"#9a7b4f","tagline":"Home items with locations, quantities, and notes.","description":"A browser-local household inventory that stores item aliases, locations, and quantities only. It holds no values, receipts, or insurance data and is not an insurance catalog, depreciation tool, or asset management system.","category":"trackers","color":"brown","height":490,"fields":[{"key":"title","label":"Item alias","type":"text","required":true,"max":60,"placeholder":"Laptop","span":"half"},{"key":"category","label":"Category","type":"select","options":["Electronics","Furniture","Appliance","Tool","Other"],"default":"Electronics","span":"half"},{"key":"location","label":"Location alias","type":"text","max":40,"placeholder":"Living room","span":"third"},{"key":"quantity","label":"Quantity","type":"number","min":1,"max":100,"step":1,"placeholder":"1","span":"third"},{"key":"condition","label":"Condition","type":"select","options":["New","Good","Fair","Needs repair"],"default":"Good","span":"third"},{"key":"note","label":"Notes","type":"text","max":100,"placeholder":"General notes, no values or receipts","span":"wide"}],"titleField":"title","cardFields":[{"key":"category","label":"Category"},{"key":"location","label":"Location"},{"key":"quantity","label":"Qty","kind":"number"},{"key":"condition","label":"Condition","kind":"priority"}],"status":{"field":"status","values":["In use","Stored","Needs repair","Discarded"],"default":"In use","colors":{"In use":"success","Stored":"info","Needs repair":"warning","Discarded":"neutral"}},"sortPriority":{"field":"condition","order":["Needs repair","Fair","Good","New"]},"dateField":{"key":"lastChecked","label":"Last checked","future":"in","past":"ago"},"metrics":[{"kind":"total"},{"kind":"sumField","field":"quantity","format":"number","label":"Total items"},{"kind":"statusCount","status":"Needs repair","label":"Needs repair"},{"kind":"statusCount","status":"Stored","label":"Stored"}],"checks":[],"search":true,"empty":"No items logged yet. Add an item above to start your inventory.","footnote":"Manual log only. Not an insurance catalog, depreciation tool, or asset management system.","submit":"Add item","searchPlaceholder":"Filter items or locations"}; (function(){ var cfgEl=document.getElementById('bk-config'),base={};try{base=cfgEl?JSON.parse(cfgEl.textContent||'{}'):{};}catch(e){} var q=new URLSearchParams(location.search),c={};for(var k in base)c[k]=base[k];q.forEach(function(v,k){c[k]=v;}); function safeColor(v,d){return /^#[0-9a-f]{6}$/i.test(String(v||''))?String(v):d;} var theme=['auto','light','dark'].indexOf(String(c.theme||'auto'))>=0?String(c.theme||'auto'):'auto',ACCENT=safeColor(c.accent,SPEC.accent),LABEL=String(c.label||SPEC.title).slice(0,48),KEY="notion-arena.household-inventory.v1",LIMIT=120; document.documentElement.setAttribute('data-theme',theme);document.documentElement.style.setProperty('--accent',ACCENT);document.getElementById('title').textContent=LABEL;document.title=LABEL; function rgb(h){var s=h.slice(1);return[0,2,4].map(function(i){return parseInt(s.slice(i,i+2),16);});}function lum(a){return a.map(function(v){v/=255;return v<=.04045?v/12.92:Math.pow((v+.055)/1.055,2.4);}).reduce(function(sum,v,i){return sum+v*[.2126,.7152,.0722][i];},0);}function ratio(a,b){var x=lum(a),y=lum(b);return(Math.max(x,y)+.05)/(Math.min(x,y)+.05);}function hex(a){return'#'+a.map(function(v){return Math.max(0,Math.min(255,v)).toString(16).padStart(2,'0');}).join('');}function mix(a,b,t){return a.map(function(v,i){return Math.round(v+(b[i]-v)*t);});}function setAccent(){var dark=theme==='dark'||(theme==='auto'&&window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches),bg=rgb(dark?'#222220':'#ffffff'),a=rgb(ACCENT),soft=mix(bg,a,.12),target=dark?[255,255,255]:[0,0,0],text=a;for(var t=.02;t<=1;t+=.02){if(ratio(text,soft)>=4.5)break;text=mix(a,target,t);}var black=[0,0,0],white=[255,255,255],ink=ratio(a,black)>=ratio(a,white)?black:white;document.documentElement.style.setProperty('--accent-text',hex(text));document.documentElement.style.setProperty('--accent-ink',hex(ink));document.documentElement.style.setProperty('--soft',hex(soft));document.documentElement.style.colorScheme=dark?'dark':'light';}setAccent();if(theme==='auto'&&window.matchMedia){var mq=window.matchMedia('(prefers-color-scheme: dark)');if(mq.addEventListener)mq.addEventListener('change',setAccent);else if(mq.addListener)mq.addListener(setAccent);} var items=[];try{var raw=JSON.parse(localStorage.getItem(KEY)||'[]');if(Array.isArray(raw))items=raw.filter(function(x){return x&&typeof x.id==='string';}).slice(0,LIMIT);}catch(e){} function el(tag,cls,text){var n=document.createElement(tag);if(cls)n.className=cls;if(text!==undefined&&text!==null)n.textContent=String(text);return n;}function clean(s,max){return String(s||'').trim().slice(0,max);}function uid(){return Date.now().toString(36)+Math.random().toString(36).slice(2,8);}function localToday(){var d=new Date();return d.getFullYear()+'-'+String(d.getMonth()+1).padStart(2,'0')+'-'+String(d.getDate()).padStart(2,'0');}function dateDiff(s){if(!/^\d{4}-\d{2}-\d{2}$/.test(String(s||'')))return null;var a=new Date(s+'T00:00:00'),b=new Date(localToday()+'T00:00:00');if(Number.isNaN(a.getTime()))return null;return Math.round((a-b)/86400000);}function prettyDate(s){if(!/^\d{4}-\d{2}-\d{2}$/.test(String(s||'')))return String(s||'');var d=new Date(s+'T12:00:00');return Number.isNaN(d.getTime())?s:d.toLocaleDateString(undefined,{month:'short',day:'numeric'});}function announce(s){document.getElementById('status').textContent=s;}function save(s){try{localStorage.setItem(KEY,JSON.stringify(items));announce(s||'Saved only in this browser.');}catch(e){announce('Browser storage is unavailable. Changes may not persist.');}} function buildForm(){var form=document.getElementById('form');SPEC.fields.forEach(function(f){var box=el('div','field '+(f.span||'half'));var id='f-'+f.key,lab=el('label','',f.label);lab.htmlFor=id;box.appendChild(lab);var input;if(f.type==='select'){input=el('select','input');(f.options||[]).forEach(function(v){var o=el('option','',v);o.value=v;input.appendChild(o);});}else if(f.type==='textarea'){input=el('textarea','input');input.rows=2;}else{input=el('input','input');input.type=f.type||'text';if(f.min!==undefined)input.min=String(f.min);if(f.max!==undefined){if(f.type==='number')input.max=String(f.max);else input.maxLength=f.max;}if(f.step!==undefined)input.step=String(f.step);}input.id=id;if(f.required)input.required=true;if(f.placeholder)input.placeholder=f.placeholder;if(f.type==='number')input.inputMode='decimal';box.appendChild(input);form.appendChild(box);});var btn=el('button','btn primary submit',SPEC.submit||'Add item');btn.type='submit';form.appendChild(btn);} buildForm(); function statusOptions(){return SPEC.status?SPEC.status.options:[];}function isDone(item){return !!(SPEC.status&&SPEC.status.done.indexOf(item.status)>=0);}function wanted(m){return m.values?m.values:(m.value!==undefined?[m.value]:[]);}function inWanted(m,v){var w=wanted(m);return !w.length||w.indexOf(v)>=0;}function num(v){return Number(v)||0;}function sumOf(rows,key){return rows.reduce(function(a,x){return a+num(x[key]);},0);} function countKind(m){if(m.kind==='total')return items.length; if(m.kind==='open')return items.filter(function(x){return!isDone(x);}).length; if(m.kind==='countStatus')return items.filter(function(x){return inWanted(m,x.status);}).length; if(m.kind==='countField')return items.filter(function(x){return(!m.excludeDone||!isDone(x))&&inWanted(m,x[m.key]);}).length; if(m.kind==='dueSoon'){var w=m.days===undefined?7:m.days;return items.filter(function(x){var n=dateDiff(x[m.key]);return!isDone(x)&&n!==null&&n>=0&&n<=w;}).length;} if(m.kind==='overdue')return items.filter(function(x){var n=dateDiff(x[m.key]);return!isDone(x)&&n!==null&&n<0;}).length; if(m.kind==='recent'){var r=m.days===undefined?7:m.days;return items.filter(function(x){var n=dateDiff(x[m.key]);return n!==null&&n<=0&&n>=-r;}).length;} if(m.kind==='sum')return sumOf(items,m.key); if(m.kind==='sumStatus')return sumOf(items.filter(function(x){return inWanted(m,x.status);}),m.key); if(m.kind==='sumField')return sumOf(items.filter(function(x){return(!m.excludeDone||!isDone(x))&&inWanted(m,x[m.by]);}),m.key); if(m.kind==='checkRate'){var all=0,done=0;items.forEach(function(x){(x.checks||[]).forEach(function(ch){all++;if(ch.done)done++;});});return all?Math.round(done/all*100):0;} if(m.kind==='rate'){var rows=items.filter(function(x){return!m.excludeDone||!isDone(x);});if(!rows.length)return 0;var hit=rows.filter(function(x){return inWanted(m,m.by?x[m.by]:x.status);}).length;return Math.round(hit/rows.length*100);} if(m.kind==='ratio'){var parts=m.parts||[m.key],top=0,total=0;items.forEach(function(x){parts.forEach(function(k,i){var v=num(x[k]);total+=v;if(!i)top+=v;});});return total?Math.round(top/total*100):0;} return 0;} function metricText(m){var n=countKind(m);if(m.format==='money')return'$'+Math.round(n).toLocaleString('en-US');if(m.format==='hours'||m.format==='days')return Number(n).toFixed(1);if(m.format==='percent')return String(n)+'%';if(m.format==='duration'){var s=Math.max(0,Math.round(n));return Math.floor(s/60)+':'+String(s%60).padStart(2,'0');}if(m.kind==='sum'&&m.key==='estimate')return'$'+Math.round(n).toLocaleString('en-US');return String(n);} function drawMetrics(){var root=document.getElementById('metrics');root.textContent='';SPEC.metrics.forEach(function(m){var box=el('div','metric');box.appendChild(el('span','metric-value',metricText(m)));box.appendChild(el('span','metric-label',m.label));root.appendChild(box);});} function makeChip(text,kind){return el('span','chip'+(kind?' '+kind:''),text);}function formatCardField(f,item){var raw=item[f.key];if(raw===undefined||raw===null||raw==='')return null;if(f.kind==='detail')return el('p','detail',String(raw));var value=String(raw);if(f.kind==='date')value=prettyDate(value);if(f.kind==='money')value='$'+num(raw).toLocaleString('en-US',{maximumFractionDigits:0})+' USD est.';if(f.kind==='number')value=f.label+': '+raw;else if(f.label&&f.kind!=='priority')value=f.label+': '+value;return makeChip(value,f.kind==='priority'?'priority':'');} function sortRows(rows){var a=rows.slice();if(SPEC.sortPriority){var p=SPEC.sortPriority.values; a.sort(function(x,y){var ax=p.indexOf(x[SPEC.sortPriority.key]),ay=p.indexOf(y[SPEC.sortPriority.key]);if(ax<0)ax=99;if(ay<0)ay=99;return ax-ay;});}if(SPEC.dateField){a.sort(function(x,y){var ax=x[SPEC.dateField]||'9999-99-99',ay=y[SPEC.dateField]||'9999-99-99';if(SPEC.sortPriority){var p=SPEC.sortPriority.values,px=p.indexOf(x[SPEC.sortPriority.key]),py=p.indexOf(y[SPEC.sortPriority.key]);if(px<0)px=99;if(py<0)py=99;if(px!==py)return px-py;}return ax.localeCompare(ay);});}return a;} function render(){drawMetrics();var root=document.getElementById('list');root.textContent='';var term=document.getElementById('search').value.trim().toLowerCase(),rows=items.filter(function(x){var hay=Object.keys(x).map(function(k){return typeof x[k]==='string'?x[k]:'';}).join(' ').toLowerCase();return!term||hay.indexOf(term)>=0;});rows=sortRows(rows);document.getElementById('count').textContent=rows.length+' shown';if(!rows.length){root.appendChild(el('div','empty',items.length?'No entries match the filter.':SPEC.empty));return;}rows.forEach(function(item){var row=el('article','entry'),main=el('div','entry-main');main.appendChild(el('div','entry-title',item[SPEC.titleField]||'Untitled'));var meta=el('div','chips');(SPEC.cardFields||[]).forEach(function(f){var n=formatCardField(f,item);if(n){if(f.kind==='detail')main.appendChild(n);else meta.appendChild(n);}});if(meta.childNodes.length)main.appendChild(meta);row.appendChild(main);var actions=el('div','actions');if(SPEC.status){var select=el('select','status');statusOptions().forEach(function(v){var o=el('option','',v);o.value=v;select.appendChild(o);});select.value=item.status||SPEC.status.default;select.setAttribute('data-status',item.id);select.setAttribute('aria-label',SPEC.status.label+' for '+(item[SPEC.titleField]||'entry'));actions.appendChild(select);}var del=el('button','remove','Remove');del.type='button';del.setAttribute('data-remove',item.id);del.setAttribute('aria-label','Remove '+(item[SPEC.titleField]||'entry'));actions.appendChild(del);row.appendChild(actions);if(SPEC.checks){var checks=el('div','checklist');(item.checks||[]).forEach(function(ch,i){var lab=el('label','check-row');var input=el('input','check');input.type='checkbox';input.checked=!!ch.done;input.setAttribute('data-check',item.id);input.setAttribute('data-index',String(i));input.id='check-'+item.id+'-'+i;lab.htmlFor=input.id;lab.appendChild(input);lab.appendChild(el('span','',ch.label));checks.appendChild(lab);});var progress=el('div','progress-row');var done=(item.checks||[]).filter(function(ch){return ch.done;}).length;progress.appendChild(el('span','small',done+' of '+(item.checks||[]).length+' checks'));var bar=el('div','bar'),fill=el('span');fill.style.width=(item.checks&&item.checks.length?Math.round(done/item.checks.length*100):0)+'%';bar.appendChild(fill);progress.appendChild(bar);checks.appendChild(progress);row.appendChild(checks);}root.appendChild(row);});} document.getElementById('form').addEventListener('submit',function(e){e.preventDefault();if(items.length>=LIMIT){announce('This local list is full. Remove an entry to add another.');return;}var item={id:uid(),status:SPEC.defaultStatus||statusOptions()[0]||''};SPEC.fields.forEach(function(f){var input=document.getElementById('f-'+f.key),v=input.value;if(f.type==='number'&&v!==''){var n=Number(v);v=Number.isFinite(n)?String(Math.min(f.max===undefined?1e9:f.max,Math.max(f.min||0,n))):'';}item[f.key]=f.type==='date'?String(v||''):clean(v,f.max||160);});if(SPEC.checks)item.checks=SPEC.checks.map(function(label){return{label:label,done:false};});items.unshift(item);try{localStorage.setItem(KEY,JSON.stringify(items));announce('Saved only in this browser.');}catch(err){announce('Browser storage is unavailable. Changes may not persist.');}this.reset();render();document.getElementById('f-'+SPEC.titleField).focus();}); document.getElementById('search').addEventListener('input',render);document.getElementById('list').addEventListener('click',function(e){var n=e.target;while(n&&n!==this){var id=n.getAttribute&&n.getAttribute('data-remove');if(id){items=items.filter(function(x){return x.id!==id;});save('Entry removed.');render();return;}n=n.parentNode;}});document.getElementById('list').addEventListener('change',function(e){var id=e.target.getAttribute('data-status');if(id){var item=items.find(function(x){return x.id===id;});if(item){item.status=e.target.value;save('State updated.');render();}return;}var checkId=e.target.getAttribute('data-check');if(checkId){var row=items.find(function(x){return x.id===checkId;});var index=Number(e.target.getAttribute('data-index'));if(row&&row.checks&&row.checks[index]){row.checks[index].done=e.target.checked;save('Checklist updated.');render();}}});document.getElementById('clear').addEventListener('click',function(){document.getElementById('search').value='';render();});render(); })();