Values editable in the top row
This commit is contained in:
parent
eb14ee71b1
commit
e0d2ab12d3
2 changed files with 61 additions and 15 deletions
64
app.js
64
app.js
|
|
@ -356,24 +356,39 @@ function resetEntryForm() {
|
||||||
|
|
||||||
function renderDashboard() {
|
function renderDashboard() {
|
||||||
const current = state.plan.current;
|
const current = state.plan.current;
|
||||||
|
const { year, month } = currentMonthParts();
|
||||||
const cards = [
|
const cards = [
|
||||||
['Feriefridage', days(current.feriefridage), 'Use before 31 August', current.feriefridage > 0.001 ? 'warn' : ''],
|
{
|
||||||
['Vacation days', days(current.vacation), 'Available today', current.vacation < -0.001 ? 'bad' : 'good'],
|
kind: 'feriefridage',
|
||||||
|
label: 'Feriefridage',
|
||||||
|
value: current.feriefridage,
|
||||||
|
hint: 'Use before 31 August',
|
||||||
|
tone: current.feriefridage > 0.001 ? 'warn' : '',
|
||||||
|
step: '0.01',
|
||||||
|
overridden: hasCorrection(state.feriefridageOverrides, year, month),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'vacation',
|
||||||
|
label: 'Vacation days',
|
||||||
|
value: current.vacation,
|
||||||
|
hint: 'Available today',
|
||||||
|
tone: current.vacation < -0.001 ? 'bad' : 'good',
|
||||||
|
step: '0.01',
|
||||||
|
overridden: hasCorrection(state.corrections, year, month),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: 'flex',
|
||||||
|
label: 'FLEX hours',
|
||||||
|
value: current.flex,
|
||||||
|
hint: 'Current balance',
|
||||||
|
tone: current.flex < -0.001 ? 'bad' : 'good',
|
||||||
|
step: '0.25',
|
||||||
|
overridden: hasCorrection(state.flexOverrides, year, month),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
$('dashboard').innerHTML = `
|
$('dashboard').innerHTML = `
|
||||||
${cards.map(([label, value, hint, tone]) => `
|
${cards.map((card) => renderDashboardBalanceCard(card, year, month)).join('')}
|
||||||
<article class="card ${tone}">
|
|
||||||
<div class="label">${escapeHtml(label)}</div>
|
|
||||||
<div class="value">${value}</div>
|
|
||||||
<div class="hint">${escapeHtml(hint)}</div>
|
|
||||||
</article>
|
|
||||||
`).join('')}
|
|
||||||
<article class="card ${current.flex < -0.001 ? 'bad' : 'good'}">
|
|
||||||
<div class="label">FLEX hours</div>
|
|
||||||
<div class="value">${hours(current.flex)}</div>
|
|
||||||
<div class="hint">Current balance</div>
|
|
||||||
</article>
|
|
||||||
<article class="card ${current.totalDays < -0.001 ? 'bad' : 'good'}">
|
<article class="card ${current.totalDays < -0.001 ? 'bad' : 'good'}">
|
||||||
<div class="label">Total days</div>
|
<div class="label">Total days</div>
|
||||||
<div class="value">${days(current.totalDays)}</div>
|
<div class="value">${days(current.totalDays)}</div>
|
||||||
|
|
@ -382,6 +397,21 @@ function renderDashboard() {
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderDashboardBalanceCard(card, year, month) {
|
||||||
|
return `
|
||||||
|
<article class="card ${card.tone}">
|
||||||
|
<div class="label">${escapeHtml(card.label)}</div>
|
||||||
|
<input class="value balance-override-input dashboard-balance-input ${card.overridden ? 'is-overridden' : ''}" type="number" step="${card.step}" value="${Number(Number(card.value || 0).toFixed(2))}" data-kind="${card.kind}" data-year="${year}" data-month="${month}" aria-label="${escapeHtml(card.label)} for current month">
|
||||||
|
<div class="hint">${escapeHtml(card.hint)}</div>
|
||||||
|
</article>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function currentMonthParts() {
|
||||||
|
const today = new Date();
|
||||||
|
return { year: today.getFullYear(), month: today.getMonth() + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
function renderHeaderWarnings() {
|
function renderHeaderWarnings() {
|
||||||
const warnings = state.plan.current.warnings;
|
const warnings = state.plan.current.warnings;
|
||||||
$('headerWarnings').innerHTML = warnings.length
|
$('headerWarnings').innerHTML = warnings.length
|
||||||
|
|
@ -444,10 +474,14 @@ function renderPlanner() {
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
bindBalanceOverrideInputs();
|
||||||
|
syncPlannerScroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindBalanceOverrideInputs() {
|
||||||
document.querySelectorAll('.balance-override-input').forEach((input) => {
|
document.querySelectorAll('.balance-override-input').forEach((input) => {
|
||||||
input.addEventListener('change', (event) => saveBalanceOverride(event).catch((error) => toast(error.message || String(error))));
|
input.addEventListener('change', (event) => saveBalanceOverride(event).catch((error) => toast(error.message || String(error))));
|
||||||
});
|
});
|
||||||
syncPlannerScroll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncPlannerScroll() {
|
function syncPlannerScroll() {
|
||||||
|
|
|
||||||
12
style.css
12
style.css
|
|
@ -175,6 +175,17 @@ main {
|
||||||
.header-cards .card .label { font-size: .88rem; font-weight: 950; white-space: nowrap; }
|
.header-cards .card .label { font-size: .88rem; font-weight: 950; white-space: nowrap; }
|
||||||
.header-cards .card .value { font-size: 1.55rem; font-weight: 950; margin: 0; }
|
.header-cards .card .value { font-size: 1.55rem; font-weight: 950; margin: 0; }
|
||||||
.header-cards .card .hint { display: none; }
|
.header-cards .card .hint { display: none; }
|
||||||
|
.header-cards .card .dashboard-balance-input {
|
||||||
|
width: 5.25rem;
|
||||||
|
min-width: 0;
|
||||||
|
padding: .05rem .18rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
text-align: right;
|
||||||
|
background: rgba(16,16,16,.55);
|
||||||
|
font-size: 1.45rem;
|
||||||
|
font-weight: 950;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
.card.bad .value { color: var(--bad); }
|
.card.bad .value { color: var(--bad); }
|
||||||
.card.warn .value { color: var(--warn); }
|
.card.warn .value { color: var(--warn); }
|
||||||
.card.good .value { color: var(--good); }
|
.card.good .value { color: var(--good); }
|
||||||
|
|
@ -397,6 +408,7 @@ tbody tr:hover { background: rgba(255,255,255,.04); }
|
||||||
.header-cards .card { padding: .14rem .2rem; gap: .18rem; }
|
.header-cards .card { padding: .14rem .2rem; gap: .18rem; }
|
||||||
.header-cards .card .label { font-size: .72rem; font-weight: 950; }
|
.header-cards .card .label { font-size: .72rem; font-weight: 950; }
|
||||||
.header-cards .card .value { font-size: 1.45rem; font-weight: 950; }
|
.header-cards .card .value { font-size: 1.45rem; font-weight: 950; }
|
||||||
|
.header-cards .card .dashboard-balance-input { width: 3.9rem; padding: .04rem .12rem; font-size: 1rem; }
|
||||||
|
|
||||||
.header-entries { padding: .16rem .22rem; margin: .16rem 0; }
|
.header-entries { padding: .16rem .22rem; margin: .16rem 0; }
|
||||||
.header-entries .table-wrap { overflow-x: visible; overflow-y: visible; }
|
.header-entries .table-wrap { overflow-x: visible; overflow-y: visible; }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue