Skip to content

Instantly share code, notes, and snippets.

@sreynen
Created August 2, 2012 15:06
Show Gist options
  • Save sreynen/3237766 to your computer and use it in GitHub Desktop.
Save sreynen/3237766 to your computer and use it in GitHub Desktop.
Time report
<?
require_once('basecamp/Basecamp.class.php'); // see http://code.google.com/p/basecamp-php-api/
$bc = new Basecamp('https://[subdomain].basecamphq.com/','[username]','[password]', 'simplexml');
$people = $bc->getPeopleForCompany([company ID]);
$person_id = array();
foreach ($people['body']->person as $person) {
$name = (string)$person->{'first-name'}[0];
$id = (int)$person->{'id'}[0];
$person_id[$name] = $id;
$id_person[$id] = $name;
} // forach
$time = $bc->getTimeEntryReport('-' . $days_past .' days', 'today');
$time_by_person_by_date = array();
foreach ($time['body']->{'time-entry'} as $time_entry) {
$this_person_id = (int)$time_entry->{'person-id'}[0];
$person = $id_person[$this_person_id];
$date = (string)$time_entry->{'date'}[0];
$hours = (float)$time_entry->{'hours'}[0];
if (!isset($time_by_person_by_date[$person])) {
$time_by_person_by_date[$person] = array();
} // if
if (!isset($time_by_person_by_date[$person][$date])) {
$time_by_person_by_date[$person][$date] = 0;
} // if
$time_by_person_by_date[$person][$date]+= $hours;
} // foreach
?>
<?
$aten_people = array(
'Ken' => '',
'Joel' => '',
'John' => '',
'Scott' => '',
'Rob' => '',
'Clayton' => 'last',
);
if ($_GET['person'] != '') {
$aten_people = array(
$_GET['person'] => 'last',
);
} // if
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>We good on time?</title>
<?
if ($_GET['subtle'] == '') {
?>
<link type="text/css" rel="stylesheet" media="all" href="style.css" />
<?
} // if
?>
</head>
<body class="styled">
<div class="container">
<div class="header">
<?
if ($_GET['subtle'] == '') {
?>
<h2>We good on time?</h2>
<?
} // if
$days_past = 7;
if ($_GET['days']) {
$days_past = intval($_GET['days']);
} // if
require_once('basecamp.php');
$day = strtotime('-' . $days_past . ' days');
$past_week = array();
while (date('Y-m-d', $day) < date('Y-m-d')) {
if (date('N', $day) < 6) {
$past_week[] = $day;
} // if
$day = strtotime(date('Y-m-d', $day) . ' +1 day');
} // while
$total_by_person = array();
ob_start();
?>
</div>
<table>
<thead>
<tr>
<th></th>
<?
foreach ($aten_people as $name => $class) {
?>
<th><?= $name ?></th>
<?
} // foreach
?>
</tr>
</thead>
<tbody>
<?
foreach ($past_week as $index => $day) {
$yesterday = $day;
$class = ' class="even"';
if ($index % 2 == 0) {
$class = ' class="odd"';
} // if
?>
<tr<?= $class ?>>
<th><em><?= date('D', $day) ?></em> <strong><?= date('m/d/Y', $day) ?></strong></th>
<?
foreach ($aten_people as $name => $class) {
?>
<td class="<= $class ?>"><a href="https://aten.basecamphq.com/time_entries/report?subject_id=<?= $person_id[$name] ?>&from%5Bmonth%5D=<?= date('n', $day) ?>&from%5Bday%5D=<?= date('j', $day) ?>&from%5Byear%5D=<?= date('Y', $day) ?>&to%5Bmonth%5D=<?= date('n', $day) ?>&to%5Bday%5D=<?= date('j', $day) ?>&to%5Byear%5D=<?= date('Y', $day) ?>&commit=Create+report"><?= number_format(floatval($time_by_person_by_date[$name][date('Y-m-d', $day)]), 2) ?></a></td>
<?
$total_by_person[$name] += $time_by_person_by_date[$name][date('Y-m-d', $day)];
} // foreach
?>
</tr>
<?
} // foreach
$day = strtotime('today');
$index++;
$class = ' class="even"';
if ($index % 2 == 0) {
$class = ' class="odd"';
} // if
?>
<tr<?= $class ?>>
<th><em><?= date('D', $day) ?></em> <strong><?= date('m/d/Y', $day) ?></strong></th>
<?
foreach ($aten_people as $name => $class) {
?>
<td class="<?= $class ?>"><a href="https://aten.basecamphq.com/time_entries/report?subject_id=<?= $person_id[$name] ?>&from%5Bmonth%5D=<?= date('n', $day) ?>&from%5Bday%5D=<?= date('j', $day) ?>&from%5Byear%5D=<?= date('Y', $day) ?>&to%5Bmonth%5D=<?= date('n', $day) ?>&to%5Bday%5D=<?= date('j', $day) ?>&to%5Byear%5D=<?= date('Y', $day) ?>&commit=Create+report"><?= number_format(floatval($time_by_person_by_date[$name][date('Y-m-d', $day)]), 2) ?></a></td>
<?
} // foreach
?>
</tr>
</tbody>
<tfoot>
<tr>
<th>Total</th>
<?
foreach ($aten_people as $name => $class) {
?>
<td class="<?= $class ?>"><?= number_format(floatval($total_by_person[$name]), 2) ?></td>
<?
} // foreach
?>
</tr>
</tfoot>
</table>
<?
$table = ob_get_clean();
if ($_GET['subtle'] == '') {
$undone = array();
$done = array();
$yesterday = date('Y-m-d', $yesterday);
foreach ($aten_people as $name => $class) {
if (
($total_by_person[$name] < 35) ||
(number_format(floatval($time_by_person_by_date[$name][$yesterday]), 2) == 0)
)
$undone[] = $name;
} // foreach
if (count($undone) > 2) {
$last = array_pop($undone);
?>
<h1 class="no">No</h1>
<p><strong><?= implode('</strong>, <strong>', $undone) ?></strong> and <strong><?= $last ?></strong> are all slacking.</p>
<?
} // if
else if (count($undone) == 2) {
?>
<h1 class="no">No</h1>
<p><strong><?= $undone[0] ?></strong> and <strong><?= $undone[1] ?></strong> are to blame.</p>
<?
} // else if
else if (count($undone) == 1) {
?>
<h1 class="no">No</h1>
<p>And it's all <strong><?= $undone[0] ?>&#8217;s</strong> fault.</p>
<?
} // else if
else {
?>
<h1 class="yes">Yes!</h1>
<div class="message"><h3>Good job!</h3></div>
<?
} // else
} // if
print $table;
?>
</div>
</body>
</html>
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}:focus{outline:0}ins{text-decoration:none}del{text-decoration:line-through}table{border-collapse:collapse;border-spacing:0}
body{font:13px/1.5 'Helvetica Neue',Helvetica,Arial,'Liberation Sans',FreeSans,sans-serif}a:focus{outline:1px dotted}hr{border:0 #ccc solid;border-top-width:1px;clear:both;height:0}h1{font-size:25px}h2{font-size:23px}h3{font-size:21px}h4{font-size:19px}h5{font-size:17px}h6{font-size:15px}ol{list-style:decimal}ul{list-style:disc}li{margin-left:30px}p,dl,hr,h1,h2,h3,h4,h5,h6,ol,ul,pre,table,address,fieldset{margin-bottom:20px}
input, textarea, select {font: 13px/1.5 'Helvetica Neue',Helvetica,Arial,'Liberation Sans',FreeSans,sans-serif;}
/* -----clearfix -----*/
/*.clear{clear:both;display:block;overflow:hidden;visibility:hidden;width:0;height:0}*/
.clearfix:after{clear:both;content:' ';display:block;font-size:0;line-height:0;visibility:hidden;width:0;height:0}* html .clearfix,*:first-child+html .clearfix{zoom:1}
/* GENERAL STYLES */
body {
text-align: center;
margin: 0;
padding: 40px 0;
}
h1 {
font-size: 10em;
line-height: 1em;
text-transform: uppercase;
font-weight: 900;
text-align: center;
}
h2 {
text-align: center;
}
table {
width: 100%;
}
thead th ,
tbody td ,
tfoot td {
text-align: center;
}
th ,
td {
padding: 8px 10px;
}
/* GENERAL CLASSES */
/* LAYOUT */
.container {
width: 600px;
margin: 0 auto;
text-align: left;
}
.header p {
text-align: center;
}
body {
background: #193ca2 url(images/bg.png) 0 0 repeat-x;
color: #fff;
}
a {
color: #fff;
text-decoration: none;
}
.header h2 {
color: #f7e2b5;
text-shadow: #112988 0 1px 0;
}
.header h1 {
text-shadow: #112988 0 1px 3px;
margin-bottom: 40px;
}
.header p {
color: #193ca2;
font-size: 1.4em;
padding: 20px 20px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
background-color: #ffffff;
-moz-box-shadow: 0px 1px 0px #000059;
-webkit-box-shadow: 0px 1px 0px #000059;
box-shadow: 0px 1px 0px #000059;
margin-bottom: 50px;
}
.header p strong {
color: #e3441f;
border-bottom: 1px dashed #e3441f;
}
.header p em {
font-family: Georgia, "Hoefler Text", Baskerville, Garamond, "Palatino Linotype", "Times New Roman", serif;
}
.header h3 {
text-align: center;
color: #f7e2b5;
text-shadow: #000045 0 1px 2px;
font-size: 2.8em;
padding: 20px 20px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
background-color: #0d2076;
-moz-box-shadow: 0px -1px 0px #000045;
-webkit-box-shadow: 0px -1px 0px #000045;
box-shadow: 0px -1px 0px #000045;
margin-bottom: 50px;
}
table {
border-collapse: separate;
}
table thead tr {
background-color: #0d2076;
border-bottom: 1px solid #000045;
color: #f7e2b5;
}
table thead tr th {
font-size: 1.3em;
border-bottom: 1px solid #0a195e;
}
table tbody tr th em {
font-style: normal;
display: inline-block;
width: 40px;
}
table tbody tr th strong {
display: inline-block;
}
table tbody tr.odd {
background-color: #1f4eba;
}
table tbody tr.odd th {
background-color: #143291;
border-right: 1px solid #0f256b;
border-top: 1px solid #193ca7;
border-bottom: 1px solid #102679;
}
table tbody tr.odd td {
border-top: 1px solid #285fc8;
border-bottom: 1px solid #193cab;
border-right: 1px solid #1e46b3;
}
table tbody tr.odd td.last {
border-right: none;
}
table tbody tr.even {
background-color: #2251c2;
}
table tbody tr.even th {
background-color: #163699;
border-right: 1px solid #0f256b;
border-top: 1px solid #1a41ad;
border-bottom: 1px solid #122b85;
}
table tbody tr.even td {
border-top: 1px solid #2961ce;
border-bottom: 1px solid #1b41b6;
border-right: 1px solid #1f49bc;
}
table tbody tr.even td.last {
border-right: none;
}
table tfoot tr {
background-color: #000045;
}
table tfoot tr th {
text-transform: uppercase;
color: #f7e2b5;
background-color: #000022;
}
table tfoot tr td {
font-size: 1.5em;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment