mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-05-23 06:40:53 -05:00
8b6e61873b
Display formats for dates and times now follow the system settings (Admin settings) by default. Users can override in their profile (User settings) or choose "Use system default" so their view matches the rest of the system. Backend: - User.date_format and User.time_format are nullable; null means use system. - Migration 120 makes these columns nullable (existing rows unchanged). - get_resolved_date_format_key() and get_resolved_time_format_key() in timezone utils return the effective key (user or system) for templates and API. - Context processor injects resolved_date_format_key and resolved_time_format_key so base.html and JS (window.userPrefs) always see the resolved format. - User settings form: "Use system default" option and save logic for null. - User.to_dict() includes resolved date_format, time_format, and timezone for API clients (e.g. mobile). Web: - base.html uses resolved keys for window.userPrefs (no hardcoded fallback). - Replaced display-only strftime() in templates with |user_date, |user_datetime, |user_time, and |format_date so all visible dates/times respect settings. Left <input type="date"> values and URL/API params as YYYY-MM-DD where required. Mobile: - ApiClient.getCurrentUser() and user prefs provider load resolved prefs from /api/v1/users/me. - date_format_utils maps API keys to intl patterns; formatDate, formatTime, formatDateTime, formatDateRange used for display. - Time entries screen (filter dialog), time entry form, time entry card, and home dashboard use user prefs for formatting; API requests still send ISO dates. Co-authored-by: Cursor <cursoragent@cursor.com>
90 lines
2.8 KiB
HTML
90 lines
2.8 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Quote Sent</title>
|
|
<style>
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
line-height: 1.6;
|
|
color: #333;
|
|
max-width: 600px;
|
|
margin: 0 auto;
|
|
padding: 20px;
|
|
background-color: #f5f5f5;
|
|
}
|
|
.container {
|
|
background-color: #ffffff;
|
|
border-radius: 8px;
|
|
padding: 30px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
}
|
|
.header {
|
|
border-bottom: 2px solid #667eea;
|
|
padding-bottom: 20px;
|
|
margin-bottom: 20px;
|
|
}
|
|
.header h1 {
|
|
color: #667eea;
|
|
margin: 0;
|
|
font-size: 24px;
|
|
}
|
|
.content {
|
|
margin-bottom: 20px;
|
|
}
|
|
.quote-details {
|
|
background-color: #f8f9fa;
|
|
border-left: 4px solid #667eea;
|
|
padding: 15px;
|
|
margin: 20px 0;
|
|
border-radius: 4px;
|
|
}
|
|
.quote-details p {
|
|
margin: 5px 0;
|
|
}
|
|
.button {
|
|
display: inline-block;
|
|
padding: 12px 24px;
|
|
background-color: #667eea;
|
|
color: #ffffff;
|
|
text-decoration: none;
|
|
border-radius: 4px;
|
|
margin: 20px 0;
|
|
}
|
|
.footer {
|
|
margin-top: 30px;
|
|
padding-top: 20px;
|
|
border-top: 1px solid #e0e0e0;
|
|
font-size: 12px;
|
|
color: #666;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="header">
|
|
<h1>{{ _('Quote Sent') }}</h1>
|
|
</div>
|
|
<div class="content">
|
|
<p>Hello {{ user.display_name or user.username }},</p>
|
|
<p>Quote <strong>{{ quote.quote_number }}</strong> has been sent to the client.</p>
|
|
|
|
<div class="quote-details">
|
|
<p><strong>Quote Number:</strong> {{ quote.quote_number }}</p>
|
|
<p><strong>Title:</strong> {{ quote.title }}</p>
|
|
<p><strong>Client:</strong> {{ quote.client.name if quote.client else 'N/A' }}</p>
|
|
<p><strong>Total Amount:</strong> {{ quote.currency_code }} {{ "%.2f"|format(quote.total_amount) }}</p>
|
|
<p><strong>Sent At:</strong> {{ quote.sent_at|user_datetime if quote.sent_at else 'N/A' }}</p>
|
|
</div>
|
|
|
|
<a href="{{ url_for('quotes.view_quote', quote_id=quote.id, _external=True) }}" class="button">{{ _('View Quote') }}</a>
|
|
</div>
|
|
<div class="footer">
|
|
<p>TimeTracker - Time Tracking & Project Management</p>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
|