Skip to content

Commit

Permalink
export csv time entries and api changes timeentries
Browse files Browse the repository at this point in the history
  • Loading branch information
storminator89 committed Dec 2, 2024
1 parent 338b8ad commit 3176787
Show file tree
Hide file tree
Showing 9 changed files with 607 additions and 256 deletions.
104 changes: 100 additions & 4 deletions api.php
Original file line number Diff line number Diff line change
Expand Up @@ -270,19 +270,115 @@ function getUsers($conn) {
/**
* @OA\Get(
* path="/api.php/timeentries",
* summary="Get all time entries for the authenticated user",
* summary="Get filtered time entries for the authenticated user",
* @OA\Parameter(
* name="start_date",
* in="query",
* description="Start date (YYYY-MM-DD)",
* required=false,
* @OA\Schema(type="string")
* ),
* @OA\Parameter(
* name="end_date",
* in="query",
* description="End date (YYYY-MM-DD)",
* required=false,
* @OA\Schema(type="string")
* ),
* @OA\Parameter(
* name="limit",
* in="query",
* description="Maximum number of entries to return",
* required=false,
* @OA\Schema(type="integer")
* ),
* @OA\Parameter(
* name="offset",
* in="query",
* description="Number of entries to skip",
* required=false,
* @OA\Schema(type="integer")
* ),
* @OA\Response(response=200, description="List of time entries"),
* @OA\Response(response=400, description="Invalid parameters"),
* @OA\Response(response=401, description="Unauthorized"),
* @OA\Response(response=500, description="Internal server error")
* )
*/
function getTimeEntries($conn, $user_id) {
try {
$stmt = $conn->prepare("SELECT * FROM zeiterfassung WHERE user_id = :user_id");
$stmt->bindParam(':user_id', $user_id, PDO::PARAM_INT);
$params = [];
$whereConditions = ["user_id = :user_id"];
$params[':user_id'] = $user_id;

// Add date filters if provided
if (isset($_GET['start_date'])) {
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $_GET['start_date'])) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'Invalid start_date format. Use YYYY-MM-DD']);
return;
}
$whereConditions[] = "date(startzeit) >= :start_date";
$params[':start_date'] = $_GET['start_date'];
}

if (isset($_GET['end_date'])) {
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $_GET['end_date'])) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'Invalid end_date format. Use YYYY-MM-DD']);
return;
}
$whereConditions[] = "date(startzeit) <= :end_date";
$params[':end_date'] = $_GET['end_date'];
}

// Build the base query
$query = "SELECT * FROM zeiterfassung WHERE " . implode(' AND ', $whereConditions);

// Add ORDER BY
$query .= " ORDER BY startzeit DESC";

// Add LIMIT and OFFSET if provided
if (isset($_GET['limit']) && is_numeric($_GET['limit'])) {
$limit = (int)$_GET['limit'];
$query .= " LIMIT :limit";
$params[':limit'] = $limit;
}

if (isset($_GET['offset']) && is_numeric($_GET['offset'])) {
$offset = (int)$_GET['offset'];
$query .= " OFFSET :offset";
$params[':offset'] = $offset;
}

// Get total count for pagination
$countStmt = $conn->prepare("SELECT COUNT(*) FROM zeiterfassung WHERE " . implode(' AND ', $whereConditions));
foreach ($params as $key => $value) {
if (!in_array($key, [':limit', ':offset'])) {
$countStmt->bindValue($key, $value);
}
}
$countStmt->execute();
$totalCount = $countStmt->fetchColumn();

// Execute main query
$stmt = $conn->prepare($query);
foreach ($params as $key => $value) {
$stmt->bindValue($key, $value);
}
$stmt->execute();
$entries = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['success' => true, 'data' => $entries]);

echo json_encode([
'success' => true,
'data' => $entries,
'meta' => [
'total' => $totalCount,
'filtered' => count($entries),
'limit' => isset($_GET['limit']) ? (int)$_GET['limit'] : null,
'offset' => isset($_GET['offset']) ? (int)$_GET['offset'] : null
]
]);
} catch (\Exception $exception) {
http_response_code(500);
echo json_encode(['success' => false, 'message' => 'Internal server error']);
Expand Down
68 changes: 68 additions & 0 deletions export_csv.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php
require_once 'config.php';
require_once 'functions.php';

// Ensure user is logged in
session_start();
if (!isset($_SESSION['user_id'])) {
die('Not authorized');
}

try {
// Set headers for CSV download with UTF-8 encoding
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename="Arbeitszeiterfassung_' . date('Y-m-d') . '.csv"');

// Create output stream with UTF-8 encoding
$output = fopen('php://temp', 'w+');
fprintf($output, "\xEF\xBB\xBF"); // UTF-8 BOM

// Add headers
fputcsv($output, [
'Datum',
'Start',
'Ende',
'Pause (Min)',
'Arbeitszeit',
'Standort',
'Beschreibung'
], ';');

// Fetch records
$stmt = $conn->prepare('
SELECT
startzeit,
endzeit,
pause,
standort,
beschreibung
FROM zeiterfassung
WHERE user_id = :user_id
ORDER BY startzeit DESC
');
$stmt->execute(['user_id' => $_SESSION['user_id']]);

while ($record = $stmt->fetch(PDO::FETCH_ASSOC)) {
$startzeit = new DateTime($record['startzeit']);
$endzeit = $record['endzeit'] ? new DateTime($record['endzeit']) : null;

fputcsv($output, [
$startzeit->format('d.m.Y'),
$startzeit->format('H:i'),
$endzeit ? $endzeit->format('H:i') : '',
$record['pause'] ?: '',
calculateDuration($record['startzeit'], $record['endzeit'], $record['pause']),
$record['standort'],
$record['beschreibung']
], ';');
}

// Output the file with UTF-8 encoding
rewind($output);
echo mb_convert_encoding(stream_get_contents($output), 'UTF-8', 'UTF-8');
fclose($output);
exit;

} catch (Exception $e) {
die('Error exporting data: ' . $e->getMessage());
}
15 changes: 14 additions & 1 deletion functions.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
<?php
include 'config.php';
session_start();

// Set default language if not set
$lang = $_SESSION['lang'] ?? 'de';
$langFile = __DIR__ . "/languages/$lang.php";

// Load language file first
if (file_exists($langFile)) {
require_once $langFile;
} else {
require_once __DIR__ . '/languages/de.php'; // Fallback to German
}

// Now include other dependencies
require_once 'config.php';

// Ensure the user is logged in
if (!isset($_SESSION['user_id'])) {
header("Location: login.php");
Expand Down
11 changes: 11 additions & 0 deletions get_time_records.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@
$currentDate = null;
$dailyTotals = [];

// Header section with improved export button
echo '<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-bold"><i class="fas fa-clock mr-2"></i>' . TABLE_HEADER_TIME_RECORDS . '</h2>
<button onclick="exportToCSV()"
class="btn btn-outline btn-success btn-sm gap-2 hover:scale-105 transform transition-transform duration-200"
>
<i class="fas fa-file-csv text-lg"></i>
<span class="hidden sm:inline">' . BUTTON_EXPORT_CSV . '</span>
</button>
</div>';

echo '<div id="timeRecordsTable" class="card bg-base-100 shadow-xl">
<div class="card-body p-6">
<h3 class="card-title text-2xl mb-6 flex items-center gap-3">
Expand Down
32 changes: 31 additions & 1 deletion index.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
<?php
<div class="event-selection-fields space-y-6">
<div class="form-control w-full">
<label class="label">
<span class="label-text font-medium">Standort</span>
</label>
<select name="standort" id="standort" class="select select-bordered w-full" required data-id="<?= htmlspecialchars($record['id']) ?>">
<option value="">Wählen Sie einen Standort</option>
<option value="Home">Home</option>
<option value="Büro">Büro</option>
</select>
</div>

<div class="form-control w-full">
<label class="label">
<span class="label-text font-medium">Kommentar</span>
</label>
<textarea name="beschreibung" id="beschreibung"
class="textarea textarea-bordered h-24"
placeholder="Geben Sie einen Kommentar ein..."
data-id="<?= htmlspecialchars($record['id']) ?>"></textarea>
</div>

<button type="submit" class="btn btn-primary w-full gap-2">
<i class="fas fa-save"></i>
Speichern
</button>
</div><?php
include 'header.php';

// Fetch user's regular working hours
Expand Down Expand Up @@ -642,6 +668,10 @@ function attachEventListeners() {
// Run on window resize
window.addEventListener('resize', updateTimeRecordsView);
});

function exportToCSV() {
window.location.href = 'export_csv.php';
}
</script>
</body>

Expand Down
7 changes: 6 additions & 1 deletion languages/de.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@
define('BUTTON_API_DOC', 'API-Dokumentation');
define('MODAL_TITLE_EDIT_USER', 'Benutzer bearbeiten');
define('FORM_REGULAR_WORKING_HOURS', 'Regelarbeitszeit');
define('FORM_OVERTIME', 'Überstunden');
define('FORM_OVERTIME', '����berstunden');
define('FORM_NEW_PASSWORD', 'Neues Passwort (leer lassen für keine Änderung)');
define('BUTTON_CANCEL', 'Abbrechen');
define('SEARCH_USERS', 'Benutzer suchen');
Expand Down Expand Up @@ -262,4 +262,9 @@

define('TOUR_START', 'Tour starten');

// Table Headers
define('TABLE_HEADER_TIME_RECORDS', 'Zeiterfassung');

define('BUTTON_EXPORT_CSV', 'CSV Export');

?>
4 changes: 4 additions & 0 deletions languages/en.php
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,10 @@

// ...existing code...
define('TOUR_START', 'Start Tour');
// Table Headers
define('TABLE_HEADER_TIME_RECORDS', 'Time Records');
// ...existing code...

define('BUTTON_EXPORT_CSV', 'CSV Export');

?>
Loading

0 comments on commit 3176787

Please sign in to comment.