feat: project scaffold with tabs, styles and package.json
This commit is contained in:
29
index.html
Normal file
29
index.html
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Morning Meeting Planner</title>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
<script src="https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Morning Meeting Planner</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<nav class="tabs">
|
||||||
|
<button class="tab-btn active" data-tab="employees">Mitarbeiter</button>
|
||||||
|
<button class="tab-btn" data-tab="planning">Monatsplanung</button>
|
||||||
|
<button class="tab-btn" data-tab="data">Daten</button>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section id="tab-employees" class="tab-content"></section>
|
||||||
|
<section id="tab-planning" class="tab-content hidden"></section>
|
||||||
|
<section id="tab-data" class="tab-content hidden"></section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script type="module" src="js/app.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
25
js/app.js
Normal file
25
js/app.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { renderEmployees } from './employees.js';
|
||||||
|
import { renderCalendar } from './calendar.js';
|
||||||
|
import { renderDataTab } from './history.js';
|
||||||
|
|
||||||
|
// Shared mutable state — imported by all other modules
|
||||||
|
export const state = {
|
||||||
|
employees: [],
|
||||||
|
calendar: { holidays: [], companyClosures: [] },
|
||||||
|
history: []
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tab switching
|
||||||
|
document.querySelectorAll('.tab-btn').forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const tab = btn.dataset.tab;
|
||||||
|
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
||||||
|
document.querySelectorAll('.tab-content').forEach(s => s.classList.add('hidden'));
|
||||||
|
btn.classList.add('active');
|
||||||
|
document.getElementById('tab-' + tab).classList.remove('hidden');
|
||||||
|
if (tab === 'planning') renderCalendar();
|
||||||
|
if (tab === 'data') renderDataTab();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
renderEmployees();
|
||||||
9
package.json
Normal file
9
package.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "morning-meeting-planner",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"start": "npx serve . -p 3000",
|
||||||
|
"test": "node tests/algorithm.test.mjs"
|
||||||
|
}
|
||||||
|
}
|
||||||
58
style.css
Normal file
58
style.css
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: system-ui, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1a1a1a;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
header { background: #2563eb; color: white; padding: 16px 24px; }
|
||||||
|
header h1 { font-size: 18px; font-weight: 600; }
|
||||||
|
|
||||||
|
.tabs { display: flex; gap: 2px; background: #e5e7eb; padding: 8px 24px 0; }
|
||||||
|
.tab-btn {
|
||||||
|
padding: 8px 20px; border: none; background: #d1d5db;
|
||||||
|
cursor: pointer; border-radius: 6px 6px 0 0; font-size: 14px; color: #374151;
|
||||||
|
}
|
||||||
|
.tab-btn.active { background: white; color: #2563eb; font-weight: 600; }
|
||||||
|
.tab-content { background: white; min-height: calc(100vh - 100px); padding: 24px; }
|
||||||
|
.hidden { display: none; }
|
||||||
|
|
||||||
|
button {
|
||||||
|
cursor: pointer; padding: 6px 14px; border-radius: 4px;
|
||||||
|
border: 1px solid #d1d5db; background: white; font-size: 13px;
|
||||||
|
}
|
||||||
|
button.primary { background: #2563eb; color: white; border-color: #2563eb; }
|
||||||
|
button.danger { background: #ef4444; color: white; border-color: #ef4444; }
|
||||||
|
input, select { padding: 5px 8px; border: 1px solid #d1d5db; border-radius: 4px; font-size: 13px; }
|
||||||
|
|
||||||
|
table { border-collapse: collapse; width: 100%; }
|
||||||
|
th, td { text-align: left; padding: 8px 12px; border-bottom: 1px solid #e5e7eb; }
|
||||||
|
th { background: #f9fafb; font-weight: 600; }
|
||||||
|
|
||||||
|
.section-title { font-size: 16px; font-weight: 600; margin-bottom: 16px; }
|
||||||
|
.row { display: flex; gap: 8px; align-items: center; margin-bottom: 12px; flex-wrap: wrap; }
|
||||||
|
|
||||||
|
.calendar-outer { overflow-x: auto; }
|
||||||
|
.calendar-header-grid { display: grid; grid-template-columns: repeat(7,1fr); gap: 6px; margin-bottom: 6px; }
|
||||||
|
.calendar-body-grid { display: grid; grid-template-columns: repeat(7,1fr); gap: 6px; }
|
||||||
|
.cal-day { border: 1px solid #e5e7eb; border-radius: 6px; padding: 8px; background: white; min-height: 80px; }
|
||||||
|
.cal-day.weekend { background: #f3f4f6; color: #9ca3af; }
|
||||||
|
.cal-day.holiday { background: #fef3c7; }
|
||||||
|
.cal-day.closure { background: #fee2e2; }
|
||||||
|
.cal-day.empty-cell { border: none; background: transparent; min-height: 0; }
|
||||||
|
.day-num { font-weight: 600; font-size: 13px; }
|
||||||
|
.day-tag { font-size: 10px; color: #6b7280; }
|
||||||
|
|
||||||
|
.employee-item { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid #f3f4f6; }
|
||||||
|
.employee-name { font-weight: 500; flex: 1; }
|
||||||
|
.constraint-form { background: #f9fafb; padding: 16px; border-radius: 8px; margin-top: 4px; margin-bottom: 8px; }
|
||||||
|
.constraint-form label { display: block; margin-bottom: 4px; font-size: 12px; color: #6b7280; }
|
||||||
|
.constraint-row { margin-bottom: 12px; }
|
||||||
|
.day-toggle-group { display: flex; gap: 4px; }
|
||||||
|
.day-toggle {
|
||||||
|
width: 32px; height: 32px; border-radius: 50%; border: 1px solid #d1d5db;
|
||||||
|
background: white; font-size: 11px; cursor: pointer;
|
||||||
|
}
|
||||||
|
.day-toggle.active { background: #2563eb; color: white; border-color: #2563eb; }
|
||||||
Reference in New Issue
Block a user