WP size: preset dropdown that sets the split threshold + show band in creator
Replaces the free-text "Typical WP Size" with a preset dropdown (Small / Standard / Large / Custom). Choosing a preset auto-fills the max-hours split threshold (still editable). The chosen band is now surfaced next to Est. Hrs in the creator's size hint (not just the View-SOP modal), alongside the threshold/over-threshold warning. Sample SOP aligned to Standard (80 hrs). repopulateForm preserves a non-preset saved value as a dropdown option. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,21 @@ let allComments = [];
|
||||
// project is active. Keeps each project's SOP separate in the browser.
|
||||
function SK(base){ try { return (typeof ProjectData !== 'undefined' && ProjectData.key) ? ProjectData.key(base) : base; } catch(e){ return base; } }
|
||||
|
||||
// WP size presets — the dropdown label maps to a default split-threshold (max
|
||||
// labor hours). The label is exported as governance.woSize (human-readable
|
||||
// guidance); the number drives the Creator's "consider splitting" warning.
|
||||
const WP_SIZE_PRESETS = {
|
||||
'Small — 1–2 days (≈8–24 hrs)': 24,
|
||||
'Standard — 3–5 days (≈40–80 hrs)': 80,
|
||||
'Large — 1–2 weeks (≈80–160 hrs)': 160
|
||||
};
|
||||
function onSizePresetChange(){
|
||||
const label = document.getElementById('gov_wosize').value;
|
||||
const max = WP_SIZE_PRESETS[label];
|
||||
if(max != null){ document.getElementById('gov_size_hours_max').value = max; }
|
||||
// 'Custom…' / '' leave the threshold for manual entry.
|
||||
}
|
||||
|
||||
let state = {
|
||||
project: {name:'', number:'', client:'', division:'', site:''},
|
||||
team: {pm:'', apm:'', cm:'', qm:''},
|
||||
@@ -181,10 +196,10 @@ function loadSampleData(){
|
||||
|
||||
// Populate Step 5
|
||||
document.getElementById('gov_woformat').value = 'WP##-[Sector]-[TYPE]';
|
||||
document.getElementById('gov_wosize').value = '3–5 days / 40–80 hours';
|
||||
document.getElementById('gov_wosize').value = 'Standard — 3–5 days (≈40–80 hrs)';
|
||||
document.getElementById('gov_disciplines').value = 'Mechanical, Electrical, Tech';
|
||||
document.getElementById('gov_discmode').value = 'choice';
|
||||
document.getElementById('gov_size_hours_max').value = '120';
|
||||
document.getElementById('gov_size_hours_max').value = '80';
|
||||
|
||||
// Populate Step 6
|
||||
document.getElementById('qual_qcreq').value = 'Yes — Detailed inspection items';
|
||||
@@ -246,6 +261,12 @@ function repopulateForm(){
|
||||
if(state.signoffRoles[0]) set('role_super_name', state.signoffRoles[0].name);
|
||||
if(state.signoffRoles[1]) set('role_foreman_name', state.signoffRoles[1].name);
|
||||
set('gov_woformat', state.governance.woformat);
|
||||
// gov_wosize is now a <select>; if a saved value isn't one of the presets
|
||||
// (e.g. legacy free text), add it as an option so the round-trip preserves it.
|
||||
const wsEl = document.getElementById('gov_wosize');
|
||||
if(wsEl && state.governance.wosize && !Array.from(wsEl.options).some(o=>o.value===state.governance.wosize)){
|
||||
wsEl.add(new Option(state.governance.wosize, state.governance.wosize));
|
||||
}
|
||||
set('gov_wosize', state.governance.wosize);
|
||||
set('gov_disciplines', (state.governance.disciplines||[]).join(', '));
|
||||
set('gov_discmode', state.governance.discMode);
|
||||
|
||||
@@ -202,13 +202,20 @@
|
||||
<div class="notice">A Work Package should be a manageable, trackable chunk of work — typically a 1–2 week assignment. The Creator warns the planner when a package exceeds the ceiling so it can be broken down.</div>
|
||||
<div class="field-grid">
|
||||
<div class="field">
|
||||
<label>Typical WP Size (guidance)</label>
|
||||
<input type="text" id="gov_wosize" placeholder="e.g., 3–5 days or 40–80 hours">
|
||||
<label>Typical WP Size</label>
|
||||
<select id="gov_wosize" onchange="onSizePresetChange()">
|
||||
<option value="">Select…</option>
|
||||
<option value="Small — 1–2 days (≈8–24 hrs)">Small — 1–2 days (≈8–24 hrs)</option>
|
||||
<option value="Standard — 3–5 days (≈40–80 hrs)">Standard — 3–5 days (≈40–80 hrs)</option>
|
||||
<option value="Large — 1–2 weeks (≈80–160 hrs)">Large — 1–2 weeks (≈80–160 hrs)</option>
|
||||
<option value="Custom…">Custom…</option>
|
||||
</select>
|
||||
<small>Sets the split threshold automatically; choose Custom to enter your own.</small>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Split threshold — max labor hours</label>
|
||||
<input type="number" id="gov_size_hours_max" min="0" step="1" placeholder="e.g., 120">
|
||||
<small>The Creator flags packages above this so they can be split (by discipline or scope).</small>
|
||||
<input type="number" id="gov_size_hours_max" min="0" step="1" placeholder="e.g., 80">
|
||||
<small>Auto-set from the size above (editable). The Creator flags packages over this so they can be split.</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@ const SAMPLE_SOP = {
|
||||
meta:{tool:'Work Package Configuration', sample:true},
|
||||
project:{name:'Micron — INC Construction Work Packages', number:'26-67-008', client:'Micron Technology, Inc.', division:'Semiconductor', pm:'Nick Siegfried', cm:'K. Boyd', qm:'D. Nguyen', site:'Boise, ID — Fab'},
|
||||
roles:[{role:'General Foreman',name:'M. Torres'},{role:'Superintendent',name:'K. Boyd'},{role:'Safety Manager / Lead',name:'A. Reyes'},{role:'Quality Manager',name:'D. Nguyen'},{role:'Planner',name:'L. Graver'}],
|
||||
governance:{ issuance:['By Sector / Area','By Discipline'], woSize:'3–5 days', woFormat:'WP##-[Sector]-[TYPE]', disciplines:['Mechanical','Electrical','Tech'], discMode:'choice', instanceSuffix:'letter', sizeHoursMax:'120' },
|
||||
governance:{ issuance:['By Sector / Area','By Discipline'], woSize:'Standard — 3–5 days (≈40–80 hrs)', woFormat:'WP##-[Sector]-[TYPE]', disciplines:['Mechanical','Electrical','Tech'], discMode:'choice', instanceSuffix:'letter', sizeHoursMax:'80' },
|
||||
woTypes:[
|
||||
{name:'Conduit Install', enabled:true}, {name:'Tray Install', enabled:true},
|
||||
{name:'Wire Pull', enabled:true}, {name:'Terminations', enabled:true},
|
||||
@@ -372,12 +372,15 @@ function rollupDisciplineStatus(){
|
||||
// ── WP SIZING WARNING (governance.sizeHoursMax) ──────────────────────────────
|
||||
function onHoursChange(){
|
||||
const el=document.getElementById('size-check'); if(!el) return;
|
||||
const max=parseFloat((SOP&&SOP.governance&&SOP.governance.sizeHoursMax)||'');
|
||||
const g=(SOP&&SOP.governance)||{};
|
||||
const band=g.woSize?('Target: '+g.woSize+'. '):'';
|
||||
const max=parseFloat(g.sizeHoursMax||'');
|
||||
const hrs=parseFloat(gv('wp_hours'));
|
||||
if(max && hrs && hrs>max){
|
||||
el.innerHTML=`<span style="color:var(--accent-amber)">⚠ ${hrs} hrs exceeds the ${max}-hr split threshold — consider breaking this package down`+(isMultiDiscipline()?' (try <strong>Split by Discipline</strong>).':'.')+`</span>`;
|
||||
} else if(max){ el.textContent=`Split threshold: ${max} hrs (from SOP).`; }
|
||||
else { el.textContent=''; }
|
||||
el.innerHTML=`<span style="color:var(--accent-amber)">${esc(band)}⚠ ${hrs} hrs exceeds the ${max}-hr split threshold — consider breaking this package down`+(isMultiDiscipline()?' (try <strong>Split by Discipline</strong>).':'.')+`</span>`;
|
||||
} else if(band || max){
|
||||
el.innerHTML=`<span>${esc(band)}${max?'Split threshold: '+max+' hrs.':''}</span>`;
|
||||
} else { el.textContent=''; }
|
||||
}
|
||||
|
||||
// ── SPLIT BY DISCIPLINE ──────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user