Skip to content

Commit 9da84b0

Browse files
committed
Make estimate template filterable
1 parent 108e77b commit 9da84b0

File tree

2 files changed

+253
-251
lines changed

2 files changed

+253
-251
lines changed

functions/admin-estimate.php

Lines changed: 4 additions & 251 deletions
Original file line numberDiff line numberDiff line change
@@ -25,255 +25,8 @@ function codeable_estimate_callback() {
2525
if ( isset( $_GET['rate'] ) && is_numeric( $_GET['rate'] ) ) {
2626
$rate = (float) $_GET['rate'];
2727
}
28-
?>
29-
<div class="wrap">
30-
<h1>PERT Estimator</h1>
31-
<form id="estimator" class="metabox-holder">
32-
<div class="estimate-row">
33-
<div id="estimates" class="postbox">
34-
<h2 class="hndle">
35-
<span>Time required to complete task</span>
36-
</h2>
37-
<div class="inside">
38-
<div class="field">
39-
<span class="label">Optimistic estimate: </span><input id="optimistic_estimate" type="number" step="0.25" min="0.25" value="1" /> hours
40-
<small><em>(the lucky case, no scope changes, ...)</em></small>
41-
</div>
42-
<div class="field">
43-
<span class="label">Most likely estimate: </span><input id="likely_estimate" type="number" step="0.25" min="0.25" value="1" /> hours
44-
<small><em>(your experience)</em></small>
45-
</div>
46-
<div class="field">
47-
<span class="label">Pessimistic estimate: </span><input id="pessimistic_estimate" type="number" step="0.25" min="0.25" value="1" /> hours
48-
<small><em>(scope changes, bad communication, technical issues, ...)</em></small>
49-
</div>
50-
</div>
51-
</div>
52-
53-
<div id="fees" class="postbox">
54-
<h2 class="hndle">
55-
<span>
56-
Rate and Fees
57-
<a href="<?php echo esc_url( admin_url( 'admin.php?page=codeable_settings' ) ); ?>"><?php esc_html_e( 'Change', 'wpcable' ); ?></a>
58-
</span>
59-
</h2>
60-
<div class="inside">
61-
<div class="field">
62-
<span class="label">Your hourly rate: </span><input id="hourly_rate" type="number" class="calc-input" value="<?php echo esc_attr( $rate ); ?>" min="35" max="1000" /> $
63-
</div>
64-
<div>
65-
<p class="description">
66-
<strong>Fees:
67-
<?php
68-
if ( 'full' === $fee_type ) {
69-
_e( 'My rate is what I want to get paid, without any fees', 'wpcable' );
70-
} elseif ( 'client' === $fee_type ) {
71-
_e( 'My rate includes my fee (10%) but not the client fee', 'wpcable' );
72-
} elseif ( 'none' === $fee_type ) {
73-
_e( 'My rate includes all fees', 'wpcable' );
74-
}
75-
?>.</strong><br />
76-
<small>Following values are used to calculate the total estimate and your earnings.</small>
77-
</p>
78-
</div>
79-
<div class="field">
80-
<span class="label">Contractor fee: </span><input id="contractor_fee" type="number" class="calc-input" step="0.01" value="<?php echo esc_attr( $fee_contractor ); ?>" max="100" min="0" /> % (your fee)
81-
</div>
82-
<div class="field">
83-
<span class="label">Client fee: </span><input id="client_fee" type="number" class="calc-input" step="0.01" value="<?php echo esc_attr( $fee_client ); ?>" max="100" min="0" /> % (depends on the client)
84-
</div>
85-
</div>
86-
</div>
87-
</div>
88-
89-
<div class="estimate-row">
90-
<div id="totals" class="postbox">
91-
<h2 class="hndle">
92-
<span>Totals</span>
93-
</h2>
94-
<div class="inside">
95-
<p class="description">
96-
Take these metrics as consideration if you put more weight on the realistic value. (Proper documentation, clear scope etc.)</p>
97-
<div class="field">
98-
<span class="label">Standard Estimate: </span><input id="estimate_hours_standard" type="text" value="" readonly="readonly"/> hours
99-
</div>
100-
<div class="field">
101-
<span class="label">Paid by the client: <br/><small>(including fees)</small></span><input id="payment" type="text" value="" readonly="readonly"/> $
102-
</div>
103-
<div class="field">
104-
<span class="label"><strong>Estimate</strong>: <br/><small>(what you enter in Codeable)</small></span><input id="estimate" type="text" value="" readonly="readonly"/> $
105-
</div>
106-
<div class="field">
107-
<span class="label">Your earnings</span><input id="earnings" type="text" value="" readonly="readonly"/> $
108-
</div>
109-
</div>
110-
</div>
111-
112-
<div id="totals_pessimistic" class="postbox">
113-
<h2 class="hndle">
114-
<span>Totals, with extra buffer</span>
115-
</h2>
116-
<div class="inside">
117-
<p class="description">
118-
Take these metrics as consideration if you put more weight on the pessimistic value. (Not proper documentation, not so clear scope etc.)</p>
119-
<div class="field">
120-
<span class="label">Cautious Estimate: </span><input id="estimate_hours_pessimistic" type="text" value="" readonly="readonly"/> hours
121-
</div>
122-
<div class="field">
123-
<span class="label">Paid by the client: <br/><small>(including fees)</small></span><input id="payment_pessimistic" type="text" value="" readonly="readonly"/> $
124-
</div>
125-
<div class="field">
126-
<span class="label"><strong>Estimate</strong>: <br/><small>(what you enter in Codeable)</small></span><input id="estimate_pessimistic" type="text" value="" readonly="readonly"/> $
127-
</div>
128-
<div class="field">
129-
<span class="label">Your earnings</span><input id="earnings_pessimistic" type="text" value="" readonly="readonly"/> $
130-
</div>
131-
</div>
132-
</div>
133-
</div>
134-
</form>
135-
</div>
136-
137-
<?php codeable_last_fetch_info(); ?>
138-
139-
<script type="text/javascript">
140-
jQuery(document).ready(function($) {
141-
function round(value, step) {
142-
step || (step = 1.0);
143-
var inv = 1.0 / step;
144-
145-
return (Math.round(value * inv) / inv)
146-
.toLocaleString(false, {minimumFractionDigits: 2, maximumFractionDigits: 2});
147-
}
148-
149-
function applyAllFees( value ) {
150-
var feeContractor = 1 / (1 - parseFloat( $('#contractor_fee').val() ) / 100);
151-
var feeClient = 1 + parseFloat( $('#client_fee').val() ) / 100;
152-
153-
<?php if ( 'full' === $fee_type ) : ?>
154-
var factor = feeContractor * feeClient;
155-
<?php elseif ( 'client' === $fee_type ) : ?>
156-
var factor = feeClient;
157-
<?php elseif ( 'none' === $fee_type ) : ?>
158-
var factor = 1;
159-
<?php endif; ?>
160-
161-
return round(value * factor, 0.01);
162-
}
163-
164-
function applyMyFees( value ) {
165-
var feeContractor = 1 / (1 - parseFloat( $('#contractor_fee').val() ) / 100);
166-
var feeClient = 1 + parseFloat( $('#client_fee').val() ) / 100;
167-
168-
<?php if ( 'full' === $fee_type ) : ?>
169-
var factor = feeContractor;
170-
<?php elseif ( 'client' === $fee_type ) : ?>
171-
var factor = 1;
172-
<?php elseif ( 'none' === $fee_type ) : ?>
173-
var factor = 1 / feeClient;
174-
<?php endif; ?>
175-
176-
return round(value * factor, 0.01);
177-
}
178-
179-
function withoutFees( value ) {
180-
var feeContractor = 1 / (1 - parseFloat( $('#contractor_fee').val() ) / 100);
181-
var feeClient = 1 + parseFloat( $('#client_fee').val() ) / 100;
182-
183-
<?php if ( 'full' === $fee_type ) : ?>
184-
var factor = 1;
185-
<?php elseif ( 'client' === $fee_type ) : ?>
186-
var factor = feeContractor;
187-
<?php elseif ( 'none' === $fee_type ) : ?>
188-
var factor = feeContractor * feeClient;
189-
<?php endif; ?>
190-
191-
return round(value / factor, 0.01);
192-
}
193-
194-
function showTime( time ) {
195-
var hours = Math.floor( time );
196-
var minutes = parseInt((time - hours) * 60);
197-
198-
return hours + ':' + ('00' + minutes).substr( -2 );
199-
}
200-
201-
function calculate() {
202-
var optimistic = parseFloat($('#optimistic_estimate').val());
203-
var likely = parseFloat($('#likely_estimate').val());
204-
var pessimistic = parseFloat($('#pessimistic_estimate').val());
205-
var rate = parseFloat($('#hourly_rate').val());
206-
207-
var estimate_hours_standard = (optimistic + 4 * likely + pessimistic) / 6;
208-
var estimate_hours_pessimistic = (optimistic + 2 * likely + 3 * pessimistic) / 6;
209-
210-
var estimate_standard = estimate_hours_standard * rate;
211-
var estimate_pessimistic = estimate_hours_pessimistic * rate;
212-
213-
$('#estimate_hours_standard').val(showTime( estimate_hours_standard ));
214-
$('#estimate_hours_pessimistic').val(showTime( estimate_hours_pessimistic ));
215-
216-
$('#payment').val(applyAllFees( estimate_standard ));
217-
$('#payment_pessimistic').val(applyAllFees( estimate_pessimistic ));
218-
219-
$('#estimate').val(applyMyFees( estimate_standard ));
220-
$('#estimate_pessimistic').val(applyMyFees( estimate_pessimistic ));
221-
222-
$('#earnings').val(withoutFees( estimate_standard ));
223-
$('#earnings_pessimistic').val(withoutFees( estimate_pessimistic ));
224-
}
225-
226-
function validateO() {
227-
var valO = parseFloat($('#optimistic_estimate').val());
228-
var valM = parseFloat($('#likely_estimate').val());
229-
var valP = parseFloat($('#pessimistic_estimate').val());
230-
231-
if (valO > valM) {
232-
$('#likely_estimate').val(valO);
233-
}
234-
if (valO > valP) {
235-
$('#pessimistic_estimate').val(valO);
236-
}
237-
238-
calculate();
239-
}
240-
241-
function validateM() {
242-
var valO = parseFloat($('#optimistic_estimate').val());
243-
var valM = parseFloat($('#likely_estimate').val());
244-
var valP = parseFloat($('#pessimistic_estimate').val());
245-
246-
if (valO > valM) {
247-
$('#optimistic_estimate').val(valM);
248-
}
249-
if (valM > valP) {
250-
$('#pessimistic_estimate').val(valM);
251-
}
252-
253-
calculate();
254-
}
255-
256-
function validateP() {
257-
var valO = parseFloat($('#optimistic_estimate').val());
258-
var valM = parseFloat($('#likely_estimate').val());
259-
var valP = parseFloat($('#pessimistic_estimate').val());
260-
261-
if (valO > valP) {
262-
$('#optimistic_estimate').val(valP);
263-
}
264-
if (valM > valP) {
265-
$('#likely_estimate').val(valP);
266-
}
267-
268-
calculate();
269-
}
270-
271-
$('.calc-input').on('change', calculate);
272-
$('#optimistic_estimate').on('change', validateO)
273-
$('#likely_estimate').on('change', validateM)
274-
$('#pessimistic_estimate').on('change', validateP)
275-
calculate();
276-
});
277-
</script>
278-
<?php
28+
$admin_estimate_template = apply_filters('wpcable_admin_estimate_template', WPCABLE_TEMPLATE_DIR.'/admin-estimate.php') ;
29+
ob_start();
30+
require_once $admin_estimate_template;
31+
echo ob_get_clean();
27932
}

0 commit comments

Comments
 (0)