Files
TimeTrack/templates/index_old.html
Jens Luedicke 4fcf4bbf80 Fix Time Tracking header jump by standardizing container classes
- Replace time-tracking-container with page-container for consistency
- Update all timetrack pages to use standard page-container class
- Remove duplicate timetrack-container class references
- This ensures consistent header positioning across all pages
2025-07-14 10:57:22 +02:00

938 lines
38 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "layout.html" %}
{% block content %}
{% if not g.user %}
<!-- Decadent Splash Page -->
<div class="splash-container">
<!-- Hero Section -->
<section class="splash-hero">
<div class="hero-content">
<h1 class="hero-title">Transform Your Productivity</h1>
<p class="hero-subtitle">Experience the future of time management with {{ g.branding.app_name if g.branding else 'TimeTrack' }}'s intelligent tracking system</p>
<div class="cta-buttons">
<a href="{{ url_for('register') }}" class="btn-primary">Get Started Free</a>
<a href="{{ url_for('login') }}" class="btn-secondary">Sign In</a>
</div>
</div>
<div class="hero-visual">
<div class="floating-clock">
<div class="clock-face">
<div class="hour-hand"></div>
<div class="minute-hand"></div>
<div class="second-hand"></div>
</div>
</div>
</div>
</section>
<!-- Features Grid -->
<section class="features-grid">
<h2 class="section-title">Powerful Features for Modern Teams</h2>
<div class="feature-cards">
<div class="feature-card">
<div class="feature-icon"><i class="ti ti-bolt"></i></div>
<h3>Lightning Fast</h3>
<p>Start tracking in seconds with our intuitive one-click interface</p>
</div>
<div class="feature-card">
<div class="feature-icon"><i class="ti ti-chart-bar"></i></div>
<h3>Advanced Analytics</h3>
<p>Gain insights with comprehensive reports and visual dashboards</p>
</div>
<div class="feature-card">
<div class="feature-icon">🏃‍♂️</div>
<h3>Sprint Management</h3>
<p>Organize work into sprints with agile project tracking</p>
</div>
<div class="feature-card">
<div class="feature-icon"><i class="ti ti-users"></i></div>
<h3>Team Collaboration</h3>
<p>Manage teams, projects, and resources all in one place</p>
</div>
<div class="feature-card">
<div class="feature-icon">🔒</div>
<h3>Enterprise Security</h3>
<p>Bank-level encryption with role-based access control</p>
</div>
<div class="feature-card">
<div class="feature-icon">🌐</div>
<h3>Multi-Company Support</h3>
<p>Perfect for agencies managing multiple client accounts</p>
</div>
</div>
</section>
<!-- Why Choose Section -->
<section class="statistics">
<h2 class="section-title">Why Choose {{ g.branding.app_name if g.branding else 'TimeTrack' }}?</h2>
<div class="stat-item">
<div class="stat-number">100%</div>
<div class="stat-label">Free & Open Source</div>
</div>
<div class="stat-item">
<div class="stat-number"><i class="ti ti-infinity"></i></div>
<div class="stat-label">Unlimited Tracking</div>
</div>
<div class="stat-item">
<div class="stat-number">0</div>
<div class="stat-label">Hidden Fees</div>
</div>
<div class="stat-item">
<div class="stat-number">24/7</div>
<div class="stat-label">Always Available</div>
</div>
</section>
<!-- Getting Started Section -->
<section class="testimonials">
<h2 class="section-title">Get Started in Minutes</h2>
<div class="testimonial-grid">
<div class="testimonial-card">
<div class="feature-icon">1</div>
<h3>Sign Up</h3>
<p>Create your free account in seconds. No credit card required.</p>
</div>
<div class="testimonial-card">
<div class="feature-icon">2</div>
<h3>Set Up Your Workspace</h3>
<p>Add your company, teams, and projects to organize your time tracking.</p>
</div>
<div class="testimonial-card">
<div class="feature-icon">3</div>
<h3>Start Tracking</h3>
<p>Click "Arrive" to start tracking, "Leave" when done. It's that simple!</p>
</div>
</div>
</section>
<!-- Open Source Section -->
<section class="pricing">
<h2 class="section-title">Forever Free, Forever Open</h2>
<div class="pricing-cards">
<div class="pricing-card featured">
<div class="badge">100% Free</div>
<h3>{{ g.branding.app_name if g.branding else 'TimeTrack' }} Community</h3>
<div class="price">$0<span>/forever</span></div>
<ul class="pricing-features">
<li><i class="ti ti-check"></i> Unlimited users</li>
<li><i class="ti ti-check"></i> All features included</li>
<li><i class="ti ti-check"></i> Time tracking & analytics</li>
<li><i class="ti ti-check"></i> Sprint management</li>
<li><i class="ti ti-check"></i> Team collaboration</li>
<li><i class="ti ti-check"></i> Project management</li>
<li><i class="ti ti-check"></i> Self-hosted option</li>
<li><i class="ti ti-check"></i> No restrictions</li>
</ul>
<a href="{{ url_for('register') }}" class="btn-pricing">Get Started Free</a>
</div>
</div>
<p style="text-align: center; margin-top: 2rem; color: #666;">
The software {{ g.branding.app_name if g.branding else 'TimeTrack' }} runs is open source software.<br />
Host it yourself or use our free hosted version.<br />
The source is available on GitHub:
<a href="https://github.com/nullmedium/TimeTrack" target="_blank">https://github.com/nullmedium/TimeTrack</a>
</p>
</section>
<!-- Final CTA -->
<section class="final-cta">
<h2>Ready to Take Control of Your Time?</h2>
<p>Start tracking your time effectively today - no strings attached</p>
<a href="{{ url_for('register') }}" class="btn-primary large">Create Free Account</a>
</section>
</div>
{% else %}
<!-- Include the modern time tracking interface from time_tracking.html -->
<div class="page-container">
<!-- Header Section -->
<div class="page-header">
<div class="header-content">
<div class="header-left">
<h1 class="page-title">
<span class="page-icon">⏱️</span>
Time Tracking
</h1>
<p class="page-subtitle">Track your work hours efficiently</p>
</div>
<div class="header-actions">
<button id="manual-entry-btn" class="btn btn-secondary">
<span class="icon">📝</span>
Manual Entry
</button>
<a href="{{ url_for('analytics') }}" class="btn btn-secondary">
<span class="icon">📊</span>
View Analytics
</a>
</div>
</div>
</div>
<!-- Timer Section -->
<div class="timer-section">
{% if active_entry %}
<!-- Active Timer -->
<div class="timer-card active">
<div class="timer-display">
<div class="timer-value" id="timer"
data-start="{{ active_entry.arrival_time.timestamp() }}"
data-breaks="{{ active_entry.total_break_duration }}"
data-paused="{{ 'true' if active_entry.is_paused else 'false' }}">
00:00:00
</div>
<div class="timer-status">
{% if active_entry.is_paused %}
<span class="status-badge paused">On Break</span>
{% else %}
<span class="status-badge active">Working</span>
{% endif %}
</div>
</div>
<div class="timer-info">
<div class="info-row">
<span class="info-label">Started:</span>
<span class="info-value">{{ active_entry.arrival_time|format_datetime }}</span>
</div>
{% if active_entry.project %}
<div class="info-row">
<span class="info-label">Project:</span>
<span class="info-value project-badge" style="background-color: {{ active_entry.project.color or '#667eea' }}">
{{ active_entry.project.code }} - {{ active_entry.project.name }}
</span>
</div>
{% endif %}
{% if active_entry.task %}
<div class="info-row">
<span class="info-label">Task:</span>
<span class="info-value task-badge">
{{ active_entry.task.title }}
</span>
</div>
{% endif %}
{% if active_entry.notes %}
<div class="info-row">
<span class="info-label">Notes:</span>
<span class="info-value">{{ active_entry.notes }}</span>
</div>
{% endif %}
{% if active_entry.is_paused %}
<div class="info-row">
<span class="info-label">Break started:</span>
<span class="info-value">{{ active_entry.pause_start_time|format_time }}</span>
</div>
{% endif %}
{% if active_entry.total_break_duration > 0 %}
<div class="info-row">
<span class="info-label">Total breaks:</span>
<span class="info-value">{{ active_entry.total_break_duration|format_duration }}</span>
</div>
{% endif %}
</div>
<div class="timer-actions">
<button id="pause-btn" class="btn {% if active_entry.is_paused %}btn-success{% else %}btn-warning{% endif %}"
data-id="{{ active_entry.id }}">
{% if active_entry.is_paused %}
<span class="icon">▶️</span>
Resume Work
{% else %}
<span class="icon">⏸️</span>
Take Break
{% endif %}
</button>
<button id="leave-btn" class="btn btn-danger" data-id="{{ active_entry.id }}">
<span class="icon">⏹️</span>
Stop Working
</button>
</div>
</div>
{% else %}
<!-- Inactive Timer -->
<div class="timer-card inactive">
<div class="start-work-container">
<h2>Start Tracking Time</h2>
<p>Select a project and task to begin tracking your work</p>
<form id="start-work-form" class="modern-form">
<div class="form-row">
<div class="form-group">
<label for="project-select" class="form-label">
Project <span class="optional-badge">Optional</span>
</label>
<select id="project-select" name="project_id" class="form-control">
<option value="">No specific project</option>
{% for project in available_projects %}
<option value="{{ project.id }}" data-color="{{ project.color or '#667eea' }}">
{{ project.code }} - {{ project.name }}
</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="task-select" class="form-label">
Task <span class="optional-badge">Optional</span>
</label>
<select id="task-select" name="task_id" class="form-control" disabled>
<option value="">Select a project first</option>
</select>
</div>
</div>
<div class="form-group">
<label for="work-notes" class="form-label">
Notes <span class="optional-badge">Optional</span>
</label>
<textarea id="work-notes" name="notes" class="form-control"
rows="2" placeholder="What are you working on?"></textarea>
</div>
<div class="form-actions">
<button type="submit" id="arrive-btn" class="btn btn-primary btn-large">
<span class="icon">▶️</span>
Start Working
</button>
</div>
</form>
</div>
</div>
{% endif %}
</div>
<!-- Quick Stats -->
{% if today_hours is defined %}
<div class="stats-section">
<div class="stat-card">
<div class="stat-value">{{ today_hours|format_duration }}</div>
<div class="stat-label">Today</div>
</div>
<div class="stat-card">
<div class="stat-value">{{ week_hours|format_duration }}</div>
<div class="stat-label">This Week</div>
</div>
<div class="stat-card">
<div class="stat-value">{{ month_hours|format_duration }}</div>
<div class="stat-label">This Month</div>
</div>
<div class="stat-card">
<div class="stat-value">{{ active_projects|length if active_projects else 0 }}</div>
<div class="stat-label">Active Projects</div>
</div>
</div>
{% endif %}
<!-- Recent Entries -->
<div class="entries-section">
<div class="section-header">
<h2 class="section-title">
<span class="icon">📋</span>
Recent Time Entries
</h2>
<div class="view-toggle">
<button class="toggle-btn active" data-view="list">
<span class="icon">📝</span>
List
</button>
<button class="toggle-btn" data-view="grid">
<span class="icon">📊</span>
Grid
</button>
</div>
</div>
<!-- List View -->
<div id="list-view" class="view-container active">
{% if history %}
<div class="entries-table-container">
<table class="entries-table">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Project / Task</th>
<th>Duration</th>
<th>Break</th>
<th>Notes</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for entry in history %}
<tr data-entry-id="{{ entry.id }}" class="entry-row">
<td>
<div class="date-cell">
<span class="date-day">{{ entry.arrival_time.strftime('%d') }}</span>
<span class="date-month">{{ entry.arrival_time.strftime('%b') }}</span>
</div>
</td>
<td>
<div class="time-cell">
<span class="time-start">{{ entry.arrival_time|format_time }}</span>
<span class="time-separator"><i class="ti ti-arrow-right"></i></span>
<span class="time-end">{{ entry.departure_time|format_time if entry.departure_time else 'Active' }}</span>
</div>
</td>
<td>
<div class="project-task-cell">
{% if entry.project %}
<span class="project-tag" style="background-color: {{ entry.project.color or '#667eea' }}">
{{ entry.project.code }}
</span>
{% endif %}
{% if entry.task %}
<span class="task-name">{{ entry.task.title }}</span>
{% elif entry.project %}
<span class="project-name">{{ entry.project.name }}</span>
{% else %}
<span class="no-project">No project</span>
{% endif %}
</div>
</td>
<td>
<span class="duration-badge">
{{ entry.duration|format_duration if entry.duration is not none else 'In progress' }}
</span>
</td>
<td>
<span class="break-duration">
{{ entry.total_break_duration|format_duration if entry.total_break_duration else '-' }}
</span>
</td>
<td>
<span class="notes-preview" title="{{ entry.notes or '' }}">
{{ entry.notes[:30] + '...' if entry.notes and entry.notes|length > 30 else entry.notes or '-' }}
</span>
</td>
<td>
<div class="actions-cell">
{% if entry.departure_time and not active_entry %}
<button class="btn-icon resume-work-btn" data-id="{{ entry.id }}" title="Resume">
<span class="icon">🔄</span>
</button>
{% endif %}
<button class="btn-icon edit-entry-btn" data-id="{{ entry.id }}" title="Edit">
<span class="icon">✏️</span>
</button>
<button class="btn-icon delete-entry-btn" data-id="{{ entry.id }}" title="Delete">
<span class="icon">🗑️</span>
</button>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="empty-state">
<div class="empty-icon">📭</div>
<h3>No time entries yet</h3>
<p>Start tracking your time to see entries here</p>
</div>
{% endif %}
</div>
<!-- Grid View -->
<div id="grid-view" class="view-container">
<div class="entries-grid">
{% for entry in history %}
<div class="entry-card" data-entry-id="{{ entry.id }}">
<div class="entry-header">
<div class="entry-date">
{{ entry.arrival_time.strftime('%d %b %Y') }}
</div>
<div class="entry-duration">
{{ entry.duration|format_duration if entry.duration is not none else 'Active' }}
</div>
</div>
<div class="entry-body">
{% if entry.project %}
<div class="entry-project" style="border-left-color: {{ entry.project.color or '#667eea' }}">
<strong>{{ entry.project.code }}</strong> - {{ entry.project.name }}
</div>
{% endif %}
{% if entry.task %}
<div class="entry-task">
<span class="icon">📋</span> {{ entry.task.title }}
</div>
{% endif %}
<div class="entry-time">
<span class="icon">🕐</span>
{{ entry.arrival_time|format_time }} - {{ entry.departure_time|format_time if entry.departure_time else 'Active' }}
</div>
{% if entry.notes %}
<div class="entry-notes">
<span class="icon">📝</span>
{{ entry.notes }}
</div>
{% endif %}
</div>
<div class="entry-footer">
<button class="btn-sm edit-entry-btn" data-id="{{ entry.id }}">Edit</button>
<button class="btn-sm btn-danger delete-entry-btn" data-id="{{ entry.id }}">Delete</button>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
<!-- Edit Entry Modal -->
<div id="edit-modal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h3>Edit Time Entry</h3>
<form id="edit-entry-form">
<input type="hidden" id="edit-entry-id">
<div class="form-group">
<label for="edit-arrival-date">Arrival Date:</label>
<input type="date" id="edit-arrival-date" required>
<small>Format: YYYY-MM-DD</small>
</div>
<div class="form-group">
<label for="edit-arrival-time">Arrival Time (24h):</label>
<input type="time" id="edit-arrival-time" required step="1">
<small>Format: HH:MM (24-hour)</small>
</div>
<div class="form-group">
<label for="edit-departure-date">Departure Date:</label>
<input type="date" id="edit-departure-date">
<small>Format: YYYY-MM-DD</small>
</div>
<div class="form-group">
<label for="edit-departure-time">Departure Time (24h):</label>
<input type="time" id="edit-departure-time" step="1">
<small>Format: HH:MM (24-hour)</small>
</div>
<button type="submit" class="btn">Save Changes</button>
</form>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div id="delete-modal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h3>Confirm Deletion</h3>
<p>Are you sure you want to delete this time entry? This action cannot be undone.</p>
<input type="hidden" id="delete-entry-id">
<div class="modal-actions">
<button id="confirm-delete" class="btn btn-danger">Delete</button>
<button id="cancel-delete" class="btn">Cancel</button>
</div>
</div>
</div>
<!-- Manual Time Entry Modal -->
<div id="manual-entry-modal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h3>Add Manual Time Entry</h3>
<form id="manual-entry-form">
<div class="form-group">
<label for="manual-project-select">Project (Optional):</label>
<select id="manual-project-select" name="project_id">
<option value="">No specific project</option>
{% for project in available_projects %}
<option value="{{ project.id }}">{{ project.code }} - {{ project.name }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="manual-start-date">Start Date:</label>
<input type="date" id="manual-start-date" required>
</div>
<div class="form-group">
<label for="manual-start-time">Start Time:</label>
<input type="time" id="manual-start-time" required step="1">
</div>
<div class="form-group">
<label for="manual-end-date">End Date:</label>
<input type="date" id="manual-end-date" required>
</div>
<div class="form-group">
<label for="manual-end-time">End Time:</label>
<input type="time" id="manual-end-time" required step="1">
</div>
<div class="form-group">
<label for="manual-break-minutes">Break Duration (minutes):</label>
<input type="number" id="manual-break-minutes" min="0" value="0" placeholder="Break time in minutes">
</div>
<div class="form-group">
<label for="manual-notes">Notes (Optional):</label>
<textarea id="manual-notes" name="notes" rows="3" placeholder="Description of work performed"></textarea>
</div>
<button type="submit" class="btn">Add Entry</button>
</form>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Manual entry functionality
document.getElementById('manual-entry-btn').addEventListener('click', function() {
// Set default dates to today
const today = new Date().toISOString().split('T')[0];
document.getElementById('manual-start-date').value = today;
document.getElementById('manual-end-date').value = today;
document.getElementById('manual-entry-modal').style.display = 'block';
});
// Manual entry form submission
document.getElementById('manual-entry-form').addEventListener('submit', function(e) {
e.preventDefault();
const projectId = document.getElementById('manual-project-select').value || null;
const startDate = document.getElementById('manual-start-date').value;
const startTime = document.getElementById('manual-start-time').value;
const endDate = document.getElementById('manual-end-date').value;
const endTime = document.getElementById('manual-end-time').value;
const breakMinutes = parseInt(document.getElementById('manual-break-minutes').value) || 0;
const notes = document.getElementById('manual-notes').value;
// Validate end time is after start time
const startDateTime = new Date(`${startDate}T${startTime}`);
const endDateTime = new Date(`${endDate}T${endTime}`);
if (endDateTime <= startDateTime) {
alert('End time must be after start time');
return;
}
// Send request to create manual entry
fetch('/api/manual-entry', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
project_id: projectId,
start_date: startDate,
start_time: startTime,
end_date: endDate,
end_time: endTime,
break_minutes: breakMinutes,
notes: notes
}),
})
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('manual-entry-modal').style.display = 'none';
location.reload(); // Refresh to show new entry
} else {
alert('Error: ' + data.message);
}
})
.catch(error => {
console.error('Error:', error);
alert('An error occurred while adding the manual entry');
});
});
// Edit entry functionality
document.querySelectorAll('.edit-entry-btn').forEach(button => {
button.addEventListener('click', function() {
const entryId = this.getAttribute('data-id');
const row = document.querySelector(`tr[data-entry-id="${entryId}"]`);
const cells = row.querySelectorAll('td');
// Get date and time from the row
const dateStr = cells[0].textContent.trim();
const arrivalTimeStr = cells[2].textContent.trim(); // arrival time is now in column 2
const departureTimeStr = cells[3].textContent.trim(); // departure time is now in column 3
// Set values in the form
document.getElementById('edit-entry-id').value = entryId;
document.getElementById('edit-arrival-date').value = dateStr;
// Format time for input (HH:MM format)
document.getElementById('edit-arrival-time').value = arrivalTimeStr.substring(0, 5);
if (departureTimeStr && departureTimeStr !== 'Active') {
document.getElementById('edit-departure-date').value = dateStr;
document.getElementById('edit-departure-time').value = departureTimeStr.substring(0, 5);
} else {
document.getElementById('edit-departure-date').value = '';
document.getElementById('edit-departure-time').value = '';
}
// Show the modal
document.getElementById('edit-modal').style.display = 'block';
});
});
// Delete entry functionality
document.querySelectorAll('.delete-entry-btn').forEach(button => {
button.addEventListener('click', function() {
const entryId = this.getAttribute('data-id');
document.getElementById('delete-entry-id').value = entryId;
document.getElementById('delete-modal').style.display = 'block';
});
});
// Close modals when clicking the X
document.querySelectorAll('.close').forEach(closeBtn => {
closeBtn.addEventListener('click', function() {
this.closest('.modal').style.display = 'none';
});
});
// Close modals when clicking outside
window.addEventListener('click', function(event) {
if (event.target.classList.contains('modal')) {
event.target.style.display = 'none';
}
});
// Cancel delete
document.getElementById('cancel-delete').addEventListener('click', function() {
document.getElementById('delete-modal').style.display = 'none';
});
// Confirm delete
document.getElementById('confirm-delete').addEventListener('click', function() {
const entryId = document.getElementById('delete-entry-id').value;
fetch(`/api/delete/${entryId}`, {
method: 'DELETE',
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Remove the row from the table
document.querySelector(`tr[data-entry-id="${entryId}"]`).remove();
// Close the modal
document.getElementById('delete-modal').style.display = 'none';
// Show success message
alert('Entry deleted successfully');
} else {
alert('Error: ' + data.message);
}
})
.catch(error => {
console.error('Error:', error);
alert('An error occurred while deleting the entry');
});
});
// Submit edit form
document.getElementById('edit-entry-form').addEventListener('submit', function(e) {
e.preventDefault();
const entryId = document.getElementById('edit-entry-id').value;
const arrivalDate = document.getElementById('edit-arrival-date').value;
const arrivalTime = document.getElementById('edit-arrival-time').value;
const departureDate = document.getElementById('edit-departure-date').value || '';
const departureTime = document.getElementById('edit-departure-time').value || '';
// Ensure we have seconds in the time strings
const arrivalTimeWithSeconds = arrivalTime.includes(':') ?
(arrivalTime.split(':').length === 2 ? arrivalTime + ':00' : arrivalTime) :
arrivalTime + ':00:00';
// Format datetime strings for the API (ISO 8601: YYYY-MM-DDTHH:MM:SS)
const arrivalDateTime = `${arrivalDate}T${arrivalTimeWithSeconds}`;
let departureDateTime = null;
if (departureDate && departureTime) {
const departureTimeWithSeconds = departureTime.includes(':') ?
(departureTime.split(':').length === 2 ? departureTime + ':00' : departureTime) :
departureTime + ':00:00';
departureDateTime = `${departureDate}T${departureTimeWithSeconds}`;
}
console.log('Sending update:', {
arrival_time: arrivalDateTime,
departure_time: departureDateTime
});
// Send update request
fetch(`/api/update/${entryId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
arrival_time: arrivalDateTime,
departure_time: departureDateTime
}),
})
.then(response => {
if (!response.ok) {
return response.json().then(data => {
throw new Error(data.message || 'Server error');
});
}
return response.json();
})
.then(data => {
if (data.success) {
// Close the modal
document.getElementById('edit-modal').style.display = 'none';
// Refresh the page to show updated data
location.reload();
} else {
alert('Error: ' + data.message);
}
})
.catch(error => {
console.error('Error:', error);
alert('An error occurred while updating the entry: ' + error.message);
});
});
});
</script>
<style>
.start-work-form {
background: #f8f9fa;
padding: 1.5rem;
border-radius: 8px;
margin-bottom: 1rem;
}
.start-work-form .form-group {
margin-bottom: 1rem;
}
.start-work-form label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
color: #333;
}
.start-work-form select,
.start-work-form textarea {
width: 100%;
padding: 0.75rem;
border: 2px solid #e9ecef;
border-radius: 6px;
font-size: 1rem;
transition: border-color 0.2s ease;
}
.start-work-form select:focus,
.start-work-form textarea:focus {
outline: none;
border-color: #4CAF50;
box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.1);
}
.project-info {
color: #4CAF50;
font-size: 0.9rem;
margin-top: 0.5rem;
}
.project-tag {
background: #4CAF50;
color: white;
padding: 0.25rem 0.5rem;
border-radius: 4px;
font-size: 0.8rem;
font-weight: 500;
margin-right: 0.5rem;
}
.project-tag + small {
color: #666;
font-size: 0.85rem;
}
.time-history td {
vertical-align: middle;
}
.time-history .project-tag + small {
display: block;
margin-top: 0.25rem;
}
.manual-entry-btn {
background: #17a2b8;
color: white;
border: none;
padding: 0.75rem 1.5rem;
border-radius: 6px;
font-size: 1rem;
cursor: pointer;
margin-left: 1rem;
transition: background-color 0.2s ease;
}
.manual-entry-btn:hover {
background: #138496;
}
.modal {
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.4);
}
.modal-content {
background-color: #fefefe;
margin: 5% auto;
padding: 20px;
border: 1px solid #888;
border-radius: 8px;
width: 500px;
max-width: 90%;
max-height: 80%;
overflow-y: auto;
}
.modal .form-group {
margin-bottom: 1rem;
}
.modal label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
color: #333;
}
.modal input,
.modal select,
.modal textarea {
width: 100%;
padding: 0.75rem;
border: 2px solid #e9ecef;
border-radius: 6px;
font-size: 1rem;
box-sizing: border-box;
}
.modal input:focus,
.modal select:focus,
.modal textarea:focus {
outline: none;
border-color: #4CAF50;
box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.1);
}
</style>
{% endif %}
{% endblock %}