3327c86909
- GenerateAiProfileDraft endpoint builds suggested AI Profile text from existing company config (ovens, workers, inventory categories, rates) - "Generate from my settings" button wired in Company Settings AI Profile tab - Add "hrs" unit label to Billable Hours/Month input in Company Settings and Setup Wizard Step 3 - Hide AI Quick Quote widget (commented out in _Layout) pending next release Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
455 lines
29 KiB
Plaintext
455 lines
29 KiB
Plaintext
@using PowderCoating.Application.DTOs.Wizard
|
||
@using PowderCoating.Core.Enums
|
||
@model WizardStep2Dto
|
||
@{
|
||
ViewData["Title"] = "Setup Wizard — Operating Costs";
|
||
var progress = ViewBag.Progress as WizardProgressDto ?? new WizardProgressDto();
|
||
int step = ViewBag.Step as int? ?? 3;
|
||
}
|
||
@section Styles { @await Html.PartialAsync("_WizardStyles") }
|
||
|
||
<div class="wizard-layout">
|
||
@await Html.PartialAsync("_WizardProgress", progress)
|
||
|
||
<div class="wizard-content">
|
||
<div class="wizard-step-header">
|
||
<span class="wizard-step-badge">Step @step of @WizardProgressDto.TotalSteps</span>
|
||
<h2><i class="bi bi-currency-dollar me-2"></i>Operating Costs</h2>
|
||
<p class="text-secondary">These rates drive the automatic pricing engine. Getting them close to your real costs means your quotes will be profitable from day one. Not sure of your numbers? Use the <strong>Help me calculate</strong> buttons next to each section.</p>
|
||
</div>
|
||
|
||
<form asp-action="PostStep3" method="post">
|
||
@Html.AntiForgeryToken()
|
||
|
||
<!-- Shop Capability Tier — quick calibration starting point -->
|
||
<div class="wizard-card">
|
||
<h5 class="wizard-card-title mb-3"><i class="bi bi-speedometer2 me-2"></i>Shop Size</h5>
|
||
<p class="text-secondary small mb-3">
|
||
This sets starting defaults for your quoting calibration — how fast your equipment can prep and coat parts.
|
||
You can fine-tune this later in <strong>Company Settings → Shop Equipment Profile</strong>.
|
||
</p>
|
||
<div class="row g-3">
|
||
<div class="col-md-8">
|
||
<label asp-for="ShopCapabilityTier" class="form-label fw-semibold">What best describes your shop?</label>
|
||
<select asp-for="ShopCapabilityTier" class="form-select">
|
||
<option value="@((int)ShopCapabilityTier.Garage)">Garage — Home setup, small compressor, part-time</option>
|
||
<option value="@((int)ShopCapabilityTier.Small)">Small — 1–5 person shop</option>
|
||
<option value="@((int)ShopCapabilityTier.Medium)">Medium — Established shop, 5–10 people</option>
|
||
<option value="@((int)ShopCapabilityTier.Large)">Large — High-volume operation, 10+ people</option>
|
||
</select>
|
||
<div class="form-text">This affects how the AI estimates sandblasting and prep time — a garage coater and a large shop blast the same wheel at very different speeds.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Labor Rates -->
|
||
<div class="wizard-card">
|
||
<h5 class="wizard-card-title mb-3">Labor Rates <button type="button" class="btn btn-link btn-sm p-0 text-primary fw-normal ms-1" data-bs-toggle="modal" data-bs-target="#laborCalcModal"><i class="bi bi-calculator me-1"></i>Help me calculate</button></h5>
|
||
<div class="row g-3">
|
||
<div class="col-md-6">
|
||
<label asp-for="StandardLaborRate" class="form-label fw-semibold"></label>
|
||
<div class="input-group">
|
||
<span class="input-group-text">$</span>
|
||
<input asp-for="StandardLaborRate" class="form-control" step="0.01" type="number" min="0" />
|
||
<span class="input-group-text">/hr</span>
|
||
</div>
|
||
<div class="form-text">Applied to every hour of hands-on work on a quote item — sandblasting, masking, coating, and general labor time all draw from this rate.</div>
|
||
<span asp-validation-for="StandardLaborRate" class="text-danger small"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Facility Overhead -->
|
||
<div class="wizard-card">
|
||
<h5 class="wizard-card-title mb-3">Facility Overhead</h5>
|
||
<p class="text-secondary small mb-3">
|
||
Enter your monthly shop rent and utilities so the system can recover those costs proportionally
|
||
across every job. Leave at zero if you work from home or your facility costs are already factored
|
||
into your markup.
|
||
</p>
|
||
<div class="row g-3">
|
||
<div class="col-md-4">
|
||
<label asp-for="MonthlyRent" class="form-label fw-semibold"></label>
|
||
<div class="input-group">
|
||
<span class="input-group-text">$</span>
|
||
<input asp-for="MonthlyRent" class="form-control wz-overhead" step="0.01" type="number" min="0" />
|
||
<span class="input-group-text">/mo</span>
|
||
</div>
|
||
<div class="form-text">Your monthly lease or rent payment for the shop space.</div>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label asp-for="MonthlyUtilities" class="form-label fw-semibold"></label>
|
||
<div class="input-group">
|
||
<span class="input-group-text">$</span>
|
||
<input asp-for="MonthlyUtilities" class="form-control wz-overhead" step="0.01" type="number" min="0" />
|
||
<span class="input-group-text">/mo</span>
|
||
</div>
|
||
<div class="form-text">Combined electricity, gas, water, and internet.</div>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label asp-for="MonthlyBillableHours" class="form-label fw-semibold"></label>
|
||
<div class="input-group">
|
||
<input asp-for="MonthlyBillableHours" class="form-control wz-overhead" step="1" type="number" min="1" />
|
||
<span class="input-group-text">hrs</span>
|
||
</div>
|
||
<div class="form-text">Hours per month the shop is actively producing work. Default: 160 (4 wks × 40 hrs).</div>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label class="form-label text-muted">Calculated overhead rate</label>
|
||
<div class="input-group">
|
||
<span class="input-group-text bg-light"><i class="bi bi-calculator"></i></span>
|
||
<input type="text" id="wzOverheadRate" class="form-control bg-light" readonly value="$0.00 / hr">
|
||
</div>
|
||
<div class="form-text">This amount is added to quotes per estimated labor hour.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Equipment Costs -->
|
||
<div class="wizard-card">
|
||
<h5 class="wizard-card-title mb-3">Equipment Costs (per hour) <button type="button" class="btn btn-link btn-sm p-0 text-primary fw-normal ms-1" data-bs-toggle="modal" data-bs-target="#equipCalcModal"><i class="bi bi-calculator me-1"></i>Help me calculate</button></h5>
|
||
<div class="row g-3">
|
||
<div class="col-md-4">
|
||
<label asp-for="SandblasterCostPerHour" class="form-label fw-semibold"></label>
|
||
<div class="input-group">
|
||
<span class="input-group-text">$</span>
|
||
<input asp-for="SandblasterCostPerHour" class="form-control" step="0.01" type="number" min="0" />
|
||
<span class="input-group-text">/hr</span>
|
||
</div>
|
||
<div class="form-text">Added to quote items that include sandblasting prep, based on estimated time in the blasting cabinet.</div>
|
||
<span asp-validation-for="SandblasterCostPerHour" class="text-danger small"></span>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label asp-for="CoatingBoothCostPerHour" class="form-label fw-semibold"></label>
|
||
<div class="input-group">
|
||
<span class="input-group-text">$</span>
|
||
<input asp-for="CoatingBoothCostPerHour" class="form-control" step="0.01" type="number" min="0" />
|
||
<span class="input-group-text">/hr</span>
|
||
</div>
|
||
<div class="form-text">Added to every quote item for time spent in the coating booth applying powder.</div>
|
||
<span asp-validation-for="CoatingBoothCostPerHour" class="text-danger small"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Materials & Pricing -->
|
||
<div class="wizard-card">
|
||
<h5 class="wizard-card-title mb-3">Materials & Pricing</h5>
|
||
<div class="row g-3">
|
||
<div class="col-md-4">
|
||
<label asp-for="PowderCoatingCostPerSqFt" class="form-label fw-semibold"></label>
|
||
<button type="button" class="btn btn-link btn-sm p-0 text-primary fw-normal ms-1" data-bs-toggle="modal" data-bs-target="#powderCalcModal"><i class="bi bi-calculator me-1"></i>Help me calculate</button>
|
||
<div class="input-group">
|
||
<span class="input-group-text">$</span>
|
||
<input asp-for="PowderCoatingCostPerSqFt" class="form-control" step="0.001" type="number" min="0" />
|
||
<span class="input-group-text">/sq ft</span>
|
||
</div>
|
||
<div class="form-text">Your powder material cost per square foot of coated surface. Multiplied by each item's surface area to calculate powder material cost on every quote.</div>
|
||
<span asp-validation-for="PowderCoatingCostPerSqFt" class="text-danger small"></span>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label asp-for="GeneralMarkupPercentage" class="form-label fw-semibold"></label>
|
||
<div class="input-group">
|
||
<input asp-for="GeneralMarkupPercentage" class="form-control" step="0.1" type="number" min="0" max="100" />
|
||
<span class="input-group-text">%</span>
|
||
</div>
|
||
<div class="form-text">Applied to the total cost of every quote to add your profit margin. A 30% markup on $100 in costs produces a $130 quote price.</div>
|
||
<span asp-validation-for="GeneralMarkupPercentage" class="text-danger small"></span>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label asp-for="TaxPercent" class="form-label fw-semibold"></label>
|
||
<div class="input-group">
|
||
<input asp-for="TaxPercent" class="form-control" step="0.01" type="number" min="0" max="100" />
|
||
<span class="input-group-text">%</span>
|
||
</div>
|
||
<div class="form-text">Sales tax rate applied to the final quote total. Set to 0 if you don't charge sales tax. Tax-exempt customers are automatically excluded.</div>
|
||
<span asp-validation-for="TaxPercent" class="text-danger small"></span>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label asp-for="ShopMinimumCharge" class="form-label fw-semibold"></label>
|
||
<div class="input-group">
|
||
<span class="input-group-text">$</span>
|
||
<input asp-for="ShopMinimumCharge" class="form-control" step="0.01" type="number" min="0" />
|
||
</div>
|
||
<div class="form-text">The lowest amount you'll charge for any job, regardless of size. If the calculated quote total falls below this, it's raised to this amount automatically.</div>
|
||
<span asp-validation-for="ShopMinimumCharge" class="text-danger small"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
@await Html.PartialAsync("_WizardFooter", step)
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════════════════════════════════════════════════════
|
||
MODAL 1 — Labor Rate Calculator
|
||
═══════════════════════════════════════════════════════════ -->
|
||
<div class="modal fade" id="laborCalcModal" tabindex="-1">
|
||
<div class="modal-dialog modal-lg">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title"><i class="bi bi-calculator me-2"></i>Labor Rate Calculator</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<p class="text-secondary small mb-3">
|
||
Your standard labor rate should cover the wages of everyone working on a job at any given time.
|
||
Enter your headcount and average wage to get a starting point.
|
||
</p>
|
||
<div class="row g-3 mb-3">
|
||
<div class="col-md-4">
|
||
<label class="form-label fw-semibold">Shop employees on floor</label>
|
||
<input type="number" id="lc_employees" class="form-control" min="1" value="2" oninput="laborCalc()" />
|
||
<div class="form-text">How many people are typically working at once.</div>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label class="form-label fw-semibold">Average hourly wage ($/hr)</label>
|
||
<div class="input-group">
|
||
<span class="input-group-text">$</span>
|
||
<input type="number" id="lc_wage" class="form-control" min="0" step="0.01" value="20" oninput="laborCalc()" />
|
||
<span class="input-group-text">/hr</span>
|
||
</div>
|
||
<div class="form-text">Blended average across all shop employees.</div>
|
||
</div>
|
||
<div class="col-md-4 d-flex align-items-end">
|
||
<div class="alert alert-info alert-permanent w-100 py-2 px-3 mb-0">
|
||
<div class="small text-secondary">Suggested labor rate</div>
|
||
<div class="fs-4 fw-bold" id="lc_result">$40.00/hr</div>
|
||
<div class="text-secondary" style="font-size:0.75rem;">employees × wage</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="alert alert-warning alert-permanent d-flex gap-2 mb-0" role="alert">
|
||
<i class="bi bi-lightbulb flex-shrink-0 mt-1"></i>
|
||
<div class="small">
|
||
<strong>Tip:</strong> This covers direct labor only. Facility and overhead costs are built into the equipment rates, and your markup percentage adds profit on top. Don't try to roll everything into the labor rate — keep them separate for accurate job costing.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||
<button type="button" class="btn btn-primary" onclick="applyLaborCalc()">
|
||
<i class="bi bi-check2-circle me-1"></i>Apply & Close
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════════════════════════════════════════════════════
|
||
MODAL 2 — Equipment Cost Calculator
|
||
═══════════════════════════════════════════════════════════ -->
|
||
<div class="modal fade" id="equipCalcModal" tabindex="-1">
|
||
<div class="modal-dialog modal-lg">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title"><i class="bi bi-calculator me-2"></i>Equipment Cost Calculator</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<p class="text-secondary small mb-3">
|
||
Equipment costs are estimated as a percentage of your monthly electric bill. Each piece of equipment draws a known share of total shop electricity. Oven cost is configured per-oven in the next step.
|
||
</p>
|
||
|
||
<div class="row g-3 mb-3">
|
||
<div class="col-md-4">
|
||
<label class="form-label fw-semibold">Monthly electric bill ($)</label>
|
||
<div class="input-group">
|
||
<span class="input-group-text">$</span>
|
||
<input type="number" id="ec_elec" class="form-control" min="0" step="1" value="0" oninput="equipCalc()" />
|
||
</div>
|
||
<div class="form-text">Your total shop electricity bill.</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="table-responsive mb-3">
|
||
<table class="table table-bordered align-middle mb-0" style="font-size:0.88rem;">
|
||
<thead class="table-light">
|
||
<tr>
|
||
<th>Equipment</th>
|
||
<th>Basis</th>
|
||
<th>Est. Monthly Cost</th>
|
||
<th>Suggested Rate</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><i class="bi bi-wind text-secondary me-1"></i>Spray Booth</td>
|
||
<td class="text-secondary small">15% of electric bill</td>
|
||
<td><strong id="ec_booth_monthly">$0.00</strong></td>
|
||
<td><strong id="ec_booth_rate" class="text-primary">$0.00/hr</strong></td>
|
||
</tr>
|
||
<tr>
|
||
<td><i class="bi bi-robot text-secondary me-1"></i>Sandblast Cabinet + Air Compressor</td>
|
||
<td class="text-secondary small">47% of electric bill <span class="text-secondary" style="font-size:0.75rem;">(12% cabinet + 35% compressor)</span></td>
|
||
<td><strong id="ec_blast_monthly">$0.00</strong></td>
|
||
<td><strong id="ec_blast_rate" class="text-primary">$0.00/hr</strong></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="alert alert-warning alert-permanent d-flex gap-2 mb-0" role="alert">
|
||
<i class="bi bi-lightbulb flex-shrink-0 mt-1"></i>
|
||
<div class="small">
|
||
<strong>Tip:</strong> These are estimates based on typical equipment power draw as a share of total shop electricity. Your actual numbers may vary — use these as a starting point and adjust based on your experience.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||
<button type="button" class="btn btn-primary" onclick="applyEquipCalc()">
|
||
<i class="bi bi-check2-circle me-1"></i>Apply & Close
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══════════════════════════════════════════════════════════
|
||
MODAL 3 — Powder Cost Calculator
|
||
═══════════════════════════════════════════════════════════ -->
|
||
<div class="modal fade" id="powderCalcModal" tabindex="-1">
|
||
<div class="modal-dialog modal-lg">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title"><i class="bi bi-calculator me-2"></i>Powder Cost Calculator</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<p class="text-secondary small mb-3">
|
||
Powder cost per sq ft is based on what you pay per pound divided by how much area you actually get out of a pound after accounting for overspray and waste.
|
||
</p>
|
||
|
||
<div class="row g-3 mb-3">
|
||
<div class="col-md-4">
|
||
<label class="form-label fw-semibold">Powder price ($/lb)</label>
|
||
<div class="input-group">
|
||
<span class="input-group-text">$</span>
|
||
<input type="number" id="pc_price" class="form-control" min="0" step="0.01" value="5.00" oninput="powderCalc()" />
|
||
<span class="input-group-text">/lb</span>
|
||
</div>
|
||
<div class="form-text">Average cost per lb across your typical powder colors.</div>
|
||
</div>
|
||
<div class="col-md-8">
|
||
<label class="form-label fw-semibold">Shop mix / coverage</label>
|
||
<select id="pc_coverage" class="form-select" onchange="powderCalc()">
|
||
<option value="100">Simple parts, flat panels — ~100 sq ft/lb</option>
|
||
<option value="80" selected>Average shop mix — ~80 sq ft/lb</option>
|
||
<option value="60">Complex / detailed parts — ~60 sq ft/lb</option>
|
||
<option value="45">Heavy rework, lots of masking — ~45 sq ft/lb</option>
|
||
</select>
|
||
<div class="form-text">Real-world coverage at 2–3 mil thickness, including overspray & waste.</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row g-3 mb-3">
|
||
<div class="col-md-6">
|
||
<div class="alert alert-info alert-permanent py-3 px-3 mb-0">
|
||
<div class="small text-secondary">Suggested powder cost</div>
|
||
<div class="fs-3 fw-bold" id="pc_result">$0.063/sq ft</div>
|
||
<div class="text-secondary small" id="pc_formula">$5.00 ÷ 80 sq ft/lb</div>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6 d-flex align-items-center">
|
||
<div class="small text-secondary">
|
||
<div class="mb-2"><strong>Typical powder prices:</strong></div>
|
||
<div>Standard solid colors $3–6/lb</div>
|
||
<div>Metallic / candy $6–10/lb</div>
|
||
<div>Specialty / texture $8–15/lb</div>
|
||
<div class="mt-2 text-secondary" style="font-size:0.75rem;">Use your blended average if you stock multiple types.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="alert alert-warning alert-permanent d-flex gap-2 mb-0" role="alert">
|
||
<i class="bi bi-lightbulb flex-shrink-0 mt-1"></i>
|
||
<div class="small">
|
||
<strong>Tip:</strong> This is your material cost only — labor and equipment are priced separately. Your markup percentage (set below) adds profit on top of all costs combined.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||
<button type="button" class="btn btn-primary" onclick="applyPowderCalc()">
|
||
<i class="bi bi-check2-circle me-1"></i>Apply & Close
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
@section Scripts {
|
||
<script>
|
||
// ── Facility Overhead Rate Preview ────────────────────────
|
||
function updateWzOverheadRate() {
|
||
var rent = parseFloat(document.querySelector('[name="MonthlyRent"]').value) || 0;
|
||
var utils = parseFloat(document.querySelector('[name="MonthlyUtilities"]').value) || 0;
|
||
var hours = parseInt(document.querySelector('[name="MonthlyBillableHours"]').value) || 1;
|
||
var rate = hours > 0 ? (rent + utils) / hours : 0;
|
||
document.getElementById('wzOverheadRate').value = '$' + rate.toFixed(2) + ' / hr';
|
||
}
|
||
document.querySelectorAll('.wz-overhead').forEach(function(el) {
|
||
el.addEventListener('input', updateWzOverheadRate);
|
||
});
|
||
updateWzOverheadRate();
|
||
|
||
// ── Labor Calculator ──────────────────────────────────────
|
||
function laborCalc() {
|
||
var employees = parseFloat(document.getElementById('lc_employees').value) || 0;
|
||
var wage = parseFloat(document.getElementById('lc_wage').value) || 0;
|
||
var rate = employees * wage;
|
||
document.getElementById('lc_result').textContent = '$' + rate.toFixed(2) + '/hr';
|
||
}
|
||
|
||
function applyLaborCalc() {
|
||
var employees = parseFloat(document.getElementById('lc_employees').value) || 0;
|
||
var wage = parseFloat(document.getElementById('lc_wage').value) || 0;
|
||
document.getElementById('StandardLaborRate').value = (employees * wage).toFixed(2);
|
||
bootstrap.Modal.getInstance(document.getElementById('laborCalcModal')).hide();
|
||
}
|
||
|
||
// ── Equipment Calculator ──────────────────────────────────
|
||
function equipCalc() {
|
||
var elec = parseFloat(document.getElementById('ec_elec').value) || 0;
|
||
|
||
var boothMonthly = elec * 0.15;
|
||
var blastMonthly = elec * 0.47;
|
||
|
||
document.getElementById('ec_booth_monthly').textContent = '$' + boothMonthly.toFixed(2);
|
||
document.getElementById('ec_blast_monthly').textContent = '$' + blastMonthly.toFixed(2);
|
||
document.getElementById('ec_booth_rate').textContent = '$' + (boothMonthly / 160).toFixed(2) + '/hr';
|
||
document.getElementById('ec_blast_rate').textContent = '$' + (blastMonthly / 160).toFixed(2) + '/hr';
|
||
}
|
||
|
||
function applyEquipCalc() {
|
||
var elec = parseFloat(document.getElementById('ec_elec').value) || 0;
|
||
document.getElementById('SandblasterCostPerHour').value = ((elec * 0.47) / 160).toFixed(2);
|
||
document.getElementById('CoatingBoothCostPerHour').value = ((elec * 0.15) / 160).toFixed(2);
|
||
bootstrap.Modal.getInstance(document.getElementById('equipCalcModal')).hide();
|
||
}
|
||
|
||
// ── Powder Calculator ─────────────────────────────────────
|
||
function powderCalc() {
|
||
var price = parseFloat(document.getElementById('pc_price').value) || 0;
|
||
var coverage = parseFloat(document.getElementById('pc_coverage').value) || 80;
|
||
var result = coverage > 0 ? price / coverage : 0;
|
||
document.getElementById('pc_result').textContent = '$' + result.toFixed(3) + '/sq ft';
|
||
document.getElementById('pc_formula').textContent = '$' + price.toFixed(2) + ' ÷ ' + coverage + ' sq ft/lb';
|
||
}
|
||
|
||
function applyPowderCalc() {
|
||
var price = parseFloat(document.getElementById('pc_price').value) || 0;
|
||
var coverage = parseFloat(document.getElementById('pc_coverage').value) || 80;
|
||
document.getElementById('PowderCoatingCostPerSqFt').value = (coverage > 0 ? price / coverage : 0).toFixed(3);
|
||
bootstrap.Modal.getInstance(document.getElementById('powderCalcModal')).hide();
|
||
}
|
||
|
||
// ── Init ──────────────────────────────────────────────────
|
||
document.getElementById('laborCalcModal').addEventListener('show.bs.modal', laborCalc);
|
||
document.getElementById('equipCalcModal').addEventListener('show.bs.modal', equipCalc);
|
||
document.getElementById('powderCalcModal').addEventListener('show.bs.modal', powderCalc);
|
||
</script>
|
||
}
|