This commit is contained in:
pika 2025-03-30 23:42:24 +02:00
parent 3b2f1db4ce
commit 5c16964b76
47 changed files with 2080 additions and 1053 deletions

9
app/static/css/tabler.min.css vendored Normal file

File diff suppressed because one or more lines are too long

165
app/static/css/theme.css Normal file
View file

@ -0,0 +1,165 @@
/* Custom theme with unique color palette */
:root {
/* Base Colors - Teal and Purple Theme */
--primary-color: #3a86ff;
--secondary-color: #8338ec;
--accent-color: #ff006e;
--success-color: #06d6a0;
--info-color: #0dcaf0;
--warning-color: #ffbe0b;
--danger-color: #ef476f;
/* Light Mode */
--bg-color: #f8fafc;
--card-bg: #ffffff;
--text-color: #1a1d23;
--text-muted: #64748b;
--border-color: rgba(226, 232, 240, 0.8);
--hover-bg: rgba(226, 232, 240, 0.4);
}
[data-bs-theme="dark"] {
/* Dark Mode */
--bg-color: #0f172a;
--card-bg: #1e293b;
--text-color: #e2e8f0;
--text-muted: #94a3b8;
--border-color: rgba(51, 65, 85, 0.7);
--hover-bg: rgba(51, 65, 85, 0.4);
}
/* Override Bootstrap classes */
.btn-primary {
background-color: var(--primary-color);
border-color: var(--primary-color);
}
.btn-primary:hover {
background-color: #2563eb;
border-color: #2563eb;
}
.btn-secondary {
background-color: var(--secondary-color);
border-color: var(--secondary-color);
}
.btn-outline-primary {
color: var(--primary-color);
border-color: var(--primary-color);
}
.text-primary {
color: var(--primary-color) !important;
}
.bg-primary {
background-color: var(--primary-color) !important;
}
/* Card styling */
.card {
border-radius: 10px;
overflow: hidden;
transition: box-shadow 0.2s ease;
border: 1px solid var(--border-color);
background-color: var(--card-bg);
}
.card:hover {
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
}
.card-header {
background-color: transparent;
border-bottom: 1px solid var(--border-color);
padding: 1rem 1.25rem;
}
.card-title {
margin-bottom: 0;
color: var(--text-color);
}
/* Table styling */
.table {
--bs-table-hover-bg: var(--hover-bg);
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: rgba(100, 116, 139, 0.5);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(100, 116, 139, 0.7);
}
/* Improved form controls */
.form-control,
.form-select {
border-radius: 8px;
border: 1px solid var(--border-color);
padding: 0.5rem 0.75rem;
background-color: var(--card-bg);
color: var(--text-color);
}
.form-control:focus,
.form-select:focus {
border-color: var(--primary-color);
box-shadow: 0 0 0 0.2rem rgba(58, 134, 255, 0.25);
}
/* Sidebar enhancements */
.sidebar {
background: linear-gradient(to bottom, #1a1d23, #0f172a);
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
}
[data-bs-theme="light"] .sidebar {
background: linear-gradient(to bottom, #f1f5f9, #e2e8f0);
}
.sidebar-item:hover {
background-color: rgba(255, 255, 255, 0.1);
}
[data-bs-theme="light"] .sidebar-item:hover {
background-color: rgba(0, 0, 0, 0.05);
}
/* Animation for page transitions */
.page-transition {
animation: fadeIn 0.3s ease-in-out;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Pill badges */
.badge {
border-radius: 50rem;
padding: 0.35em 0.65em;
font-weight: 500;
font-size: 0.75em;
}

BIN
app/static/img/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View file

@ -1,3 +1,7 @@
/**
* DITTO Application JavaScript
* Modern ES6+ syntax with proper error handling
*/
document.addEventListener('DOMContentLoaded', () => {
console.log('App script loaded.');
@ -76,8 +80,121 @@ document.addEventListener('DOMContentLoaded', () => {
// Initialize notifications
initNotifications();
});
// Initialize Bootstrap components
initBootstrapComponents();
// Setup sidebar toggle functionality
setupSidebar();
// Add form validation
setupFormValidation();
});
/**
* Initialize Bootstrap components
*/
function initBootstrapComponents() {
// Initialize all tooltips
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
tooltipTriggerList.forEach(el => {
try {
new bootstrap.Tooltip(el);
} catch (e) {
console.warn('Error initializing tooltip:', e);
}
});
// Initialize all popovers
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]');
popoverTriggerList.forEach(el => {
try {
new bootstrap.Popover(el);
} catch (e) {
console.warn('Error initializing popover:', e);
}
});
}
/**
* Setup sidebar toggle functionality
*/
function setupSidebar() {
const sidebarToggler = document.querySelector('.sidebar-toggler');
const sidebar = document.querySelector('.sidebar');
if (sidebarToggler && sidebar) {
sidebarToggler.addEventListener('click', () => {
sidebar.classList.toggle('show');
});
// Close sidebar when clicking outside on mobile
document.addEventListener('click', (event) => {
const isClickInside = sidebar.contains(event.target) ||
sidebarToggler.contains(event.target);
if (!isClickInside && sidebar.classList.contains('show') && window.innerWidth < 992) {
sidebar.classList.remove('show');
}
});
}
}
/**
* Setup form validation
*/
function setupFormValidation() {
// Add custom validation for forms
const forms = document.querySelectorAll('.needs-validation');
forms.forEach(form => {
form.addEventListener('submit', event => {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}
/**
* Safe query selector with error handling
* @param {string} selector - CSS selector
* @param {Element} parent - Parent element (optional)
* @returns {Element|null} - The selected element or null
*/
function $(selector, parent = document) {
try {
return parent.querySelector(selector);
} catch (e) {
console.warn(`Error selecting "${selector}":`, e);
return null;
}
}
/**
* Format date for display
* @param {string|Date} date - Date to format
* @returns {string} - Formatted date string
*/
function formatDate(date) {
try {
const d = new Date(date);
return d.toLocaleDateString(undefined, {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
} catch (e) {
console.warn('Error formatting date:', e);
return String(date);
}
}
function initTiptapEditor(element) {
// Load required Tiptap scripts
const editorContainer = document.getElementById('editor-container');

File diff suppressed because one or more lines are too long