function createCreateAndStart({ todayWork, todaySync, refresh, warm, start, announce }) { const completed = new Set(); function available() { return todayWork.read().length < todayWork.limit; } function capacity(value) { if (String(value ?? '').trim() === '') return { valid: false, reason: 'required' }; const minutes = Number(value); if (!Number.isInteger(minutes) || minutes < 5 || minutes > 1440) { return { valid: false, reason: 'range' }; } const plan = todayWork.planning(); const capacityMinutes = plan.capacity_minutes; if (!Number.isInteger(capacityMinutes)) { return { valid: true, minutes, capacityMinutes: null, plannedMinutes: null, remainingMinutes: null, projectedMinutes: null, fits: true }; } const plannedMinutes = todayWork.read().reduce( (total, identity) => total + (Number.isInteger(plan.estimates[identity]) ? plan.estimates[identity] : 0), 0 ); const remainingMinutes = capacityMinutes - plannedMinutes; const projectedMinutes = remainingMinutes - minutes; return { valid: true, minutes, capacityMinutes, plannedMinutes, remainingMinutes, projectedMinutes, fits: projectedMinutes >= 0 }; } function capacityMessage(result) { if (!result.valid) return result.reason === 'required' ? 'Required only for Create & start.' : 'Use a whole number from 5 to 1440 minutes.'; if (result.capacityMinutes === null) { return result.minutes + ' min · Set a Today budget to see remaining time.'; } return result.fits ? result.minutes + ' min · ' + result.projectedMinutes + ' min will remain in Today.' : result.minutes + ' min · ' + Math.abs(result.projectedMinutes) + ' min over Today capacity.'; } function complete(issue, estimateMinutes) { const identity = todayWork.identity(issue); if (!identity || completed.has(identity)) return 'exists'; const added = todayWork.add(issue); if (added === 'full') { announce('Created, but Today changed—remove an item, then add this issue.'); return 'full'; } if (added !== 'added' && added !== 'exists') { announce('Created, but Today could not be saved on this device.'); return 'unavailable'; } let estimatedPlan = null; if (Number.isInteger(estimateMinutes)) { estimatedPlan = todayWork.planning(); estimatedPlan.estimates[identity] = estimateMinutes; if (!todayWork.replacePlanning(estimatedPlan)) { announce('Created and added to Today, but its estimate could not be saved on this device.'); return 'estimate-unavailable'; } } if (!todaySync.enqueue('add', identity)) { announce('Created and saved to Today on this device, but account sync is unavailable.'); return 'sync-unavailable'; } if (estimatedPlan) { if (!todaySync.enqueueConfiguration(estimatedPlan.capacity_minutes, estimatedPlan.estimates)) { announce('Created and estimated on this device, but Today plan sync is unavailable.'); return 'sync-unavailable'; } } completed.add(identity); refresh(); todaySync.flush(); warm(); start(issue); announce('Created, added to Today, and ready to work.'); return 'started'; } return { available, capacity, capacityMessage, complete }; } if (typeof module !== 'undefined' && module.exports) module.exports = createCreateAndStart;