Compare commits

..

2 Commits

4 changed files with 33 additions and 96 deletions

View File

@@ -67,65 +67,12 @@ Die Anwendung berechnet automatisch die Pausenzeiten gemäß deutschem Arbeitsze
- `DELETE /api/entries/:id` - Eintrag löschen - `DELETE /api/entries/:id` - Eintrag löschen
- `GET /api/export?from=YYYY-MM-DD&to=YYYY-MM-DD` - Einträge als CSV exportieren - `GET /api/export?from=YYYY-MM-DD&to=YYYY-MM-DD` - Einträge als CSV exportieren
## Installation & Ausführung ## Lokale Ausführung
### Repository klonen ### Voraussetzungen
```bash
git clone https://gitea.fx-se.de/maggot/timetracker.git
cd timetracker
```
### Option 1: Mit Docker Compose (Empfohlen)
**Voraussetzungen:**
- Docker und Docker Compose installiert
**Starten:**
```bash
docker-compose up -d
```
**Logs ansehen:**
```bash
docker-compose logs -f
```
**Stoppen:**
```bash
docker-compose down
```
**Stoppen und Daten löschen:**
```bash
docker-compose down -v
```
Die Anwendung läuft auf:
```
http://localhost:3000
```
### Option 2: Mit Docker (manuell)
**Docker-Image erstellen:**
```bash
docker build -t zeiterfassung .
```
**Container starten:**
```bash
docker run -p 3000:3000 -v $(pwd)/db:/app/db zeiterfassung
```
Das `-v` Flag bindet das Datenbankverzeichnis ein, um Daten zwischen Container-Neustarts zu erhalten.
### Option 3: Lokale Ausführung (ohne Docker)
**Voraussetzungen:**
- Node.js 18+ installiert - Node.js 18+ installiert
**Installation:** ### Installation
1. Abhängigkeiten installieren: 1. Abhängigkeiten installieren:
```bash ```bash
@@ -142,6 +89,25 @@ npm start
http://localhost:3000 http://localhost:3000
``` ```
## Ausführung mit Docker
### Docker-Image erstellen:
```bash
docker build -t zeiterfassung .
```
### Container starten:
```bash
docker run -p 3000:3000 -v $(pwd)/db:/app/db zeiterfassung
```
Das `-v` Flag bindet das Datenbankverzeichnis ein, um Daten zwischen Container-Neustarts zu erhalten.
### Anwendung aufrufen:
```
http://localhost:3000
```
## CSV-Export-Format ## CSV-Export-Format
Die exportierte CSV-Datei enthält folgende Spalten: Die exportierte CSV-Datei enthält folgende Spalten:

View File

@@ -1,27 +0,0 @@
version: '3.8'
services:
timetracker:
build:
context: .
dockerfile: Dockerfile
container_name: timetracker-app
ports:
- "3000:3000"
volumes:
# Persistent volume for SQLite database
- timetracker-data:/app/db
environment:
- NODE_ENV=production
- PORT=3000
restart: unless-stopped
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"]
interval: 30s
timeout: 3s
retries: 3
start_period: 5s
volumes:
timetracker-data:
driver: local

View File

@@ -1462,9 +1462,7 @@ async function bulkSetLocation(location) {
for (const id of selectedEntries) { for (const id of selectedEntries) {
const entry = entries.find(e => e.id === id); const entry = entries.find(e => e.id === id);
if (entry) { if (entry) {
// Convert date from YYYY-MM-DD to DD.MM.YYYY for updateEntry const success = await updateEntry(id, entry.date, entry.startTime, entry.endTime, entry.pauseMinutes, location);
const formattedDate = formatDateDisplay(entry.date);
const success = await updateEntry(id, formattedDate, entry.startTime, entry.endTime, entry.pauseMinutes, location);
if (success) { if (success) {
updated++; updated++;
} }

View File

@@ -308,20 +308,20 @@
<!-- Entries Table --> <!-- Entries Table -->
<div class="bg-gray-800 rounded-lg shadow-md overflow-hidden border border-gray-700"> <div class="bg-gray-800 rounded-lg shadow-md overflow-hidden border border-gray-700">
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table class="w-full"> <table class="w-full table-fixed">
<thead class="bg-gray-700 border-b border-gray-600"> <thead class="bg-gray-700 border-b border-gray-600">
<tr> <tr>
<th id="checkboxHeader" class="hidden px-2 py-3 text-center text-xs font-medium text-gray-400 uppercase tracking-wider"> <th id="checkboxHeader" class="hidden w-12 px-2 py-3 text-center text-xs font-medium text-gray-400 uppercase tracking-wider">
<input type="checkbox" id="masterCheckbox" class="w-5 h-5 text-blue-600 bg-gray-700 border-gray-600 rounded focus:ring-blue-500" title="Alle auswählen/abwählen"> <input type="checkbox" id="masterCheckbox" class="w-5 h-5 text-blue-600 bg-gray-700 border-gray-600 rounded focus:ring-blue-500" title="Alle auswählen/abwählen">
</th> </th>
<th class="px-2 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Tag</th> <th class="w-12 px-2 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Tag</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Datum</th> <th class="w-28 px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Datum</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Start</th> <th class="w-20 px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Start</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Ende</th> <th class="w-20 px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Ende</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Pause (Min)</th> <th class="w-28 px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Pause (Min)</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Netto (Std)</th> <th class="w-28 px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">Netto (Std)</th>
<th class="px-6 py-3 text-center text-xs font-medium text-gray-400 uppercase tracking-wider">Ort</th> <th class="w-24 px-6 py-3 text-center text-xs font-medium text-gray-400 uppercase tracking-wider">Ort</th>
<th class="px-6 py-3 text-center text-xs font-medium text-gray-400 uppercase tracking-wider">Action</th> <th class="w-24 px-6 py-3 text-center text-xs font-medium text-gray-400 uppercase tracking-wider">Action</th>
</tr> </tr>
</thead> </thead>
<tbody id="entriesTableBody" class="bg-gray-800 divide-y divide-gray-700"> <tbody id="entriesTableBody" class="bg-gray-800 divide-y divide-gray-700">