- Thin animated bar at page top shows while any fetch is in-flight - api() centrally redirects to login on 401 (except login endpoint) - Logo click triggers manual goal refresh - cursor:pointer on logo Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
362 lines
15 KiB
Twig
362 lines
15 KiB
Twig
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8"/>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
|
||
<meta name="theme-color" content="#f5f4f0"/>
|
||
<meta name="mobile-web-app-capable" content="yes"/>
|
||
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
||
<title>Dudi</title>
|
||
<link rel="stylesheet" href="style.css?v={{ cssv }}"/>
|
||
</head>
|
||
<body>
|
||
<div id="api-bar"></div>
|
||
<div class="main-wrap">
|
||
<div class="hdr">
|
||
<div>
|
||
<img src="logo.png" alt="Dudi" class="hdr-logo"/>
|
||
<div class="hdr-sub" id="tlbl"></div>
|
||
</div>
|
||
<span id="sw" class="sw">0.00s</span>
|
||
<div class="hdr-btns">
|
||
<button class="btn-menu" id="btnData">⋯</button>
|
||
<button class="btn-add" id="btnNew">+</button>
|
||
</div>
|
||
</div>
|
||
<div class="main" id="main"></div>
|
||
</div>
|
||
<div id="ov" style="display:none"></div>
|
||
|
||
<!-- ── Templates ──────────────────────────────────────────────────────────── -->
|
||
|
||
<template id="tpl-hint">
|
||
<div class="hint"><span data-t="hint"></span><button class="hclose">×</button></div>
|
||
</template>
|
||
|
||
<template id="tpl-empty">
|
||
<div class="empty"><div style="font-size:40px;opacity:.4;margin-bottom:12px">🎯</div><span data-t="emptyLine1"></span><br><span data-t="emptyLine2"></span></div>
|
||
</template>
|
||
|
||
<template id="tpl-dot">
|
||
<div></div>
|
||
</template>
|
||
|
||
<template id="tpl-nosets">
|
||
<div class="nosets" data-t="noEntry"></div>
|
||
</template>
|
||
|
||
<template id="tpl-set-row">
|
||
<div class="set-row">
|
||
<span></span>
|
||
<button class="sdel">×</button>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-add-row">
|
||
<div class="add-row">
|
||
<input class="num-in" type="number" min="1"/>
|
||
<span class="ulbl"></span>
|
||
<button class="btn-sw-fill" style="display:none">⏱</button>
|
||
<button class="btn-as" data-t="log"></button>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-panel">
|
||
<div class="dpanel">
|
||
<div class="dpanel-hdr">
|
||
<span class="dpanel-title"></span>
|
||
<span class="dpanel-sub"></span>
|
||
</div>
|
||
<div class="dpanel-body"></div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-qb-row">
|
||
<div class="qb-row">
|
||
<div class="qb-name"></div>
|
||
<div class="qb-stat"></div>
|
||
<input class="num-in" type="number" min="1"/>
|
||
<button class="btn-sw-fill" style="display:none">⏱</button>
|
||
<button class="btn-as" data-t="log"></button>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-name-view">
|
||
<div class="name-wrap">
|
||
<div class="goal-name"></div>
|
||
<button class="btn-ren">✎</button>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-name-edit">
|
||
<div class="name-wrap">
|
||
<input class="ren-input" type="text"/>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-card-collapsed">
|
||
<div class="card">
|
||
<div class="card-hdr">
|
||
<div class="card-bd" style="flex:1;min-width:0">
|
||
<div class="goal-meta"><span data-t="noch"></span> <span class="m-dr"></span><span data-t="dAbbr"></span> · <span data-t="endet"></span> <span class="m-end"></span> · <span data-t="todayShort"></span>: <span class="m-heute"></span><br><span data-t="total"></span>: <span class="m-total"></span></div>
|
||
</div>
|
||
<span class="badge"></span>
|
||
<span class="chevron">▸</span>
|
||
</div>
|
||
<div style="padding:0 16px 12px">
|
||
<div class="prog-track"><div class="prog-fill"></div></div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-card-expanded">
|
||
<div class="card">
|
||
<div class="card-hdr">
|
||
<div class="card-bd" style="flex:1;min-width:0">
|
||
<div class="goal-meta"><span data-t="noch"></span> <span class="m-dr"></span><span data-t="dAbbr"></span> · <span data-t="endet"></span> <span class="m-end"></span></div>
|
||
</div>
|
||
<span class="badge"></span>
|
||
<span class="chevron">▴</span>
|
||
</div>
|
||
<div class="prog-wrap">
|
||
<div class="prog-track"><div class="prog-fill"></div></div>
|
||
<div class="prog-row">
|
||
<span class="pr-done"></span>
|
||
<span class="pr-pct"></span>
|
||
</div>
|
||
</div>
|
||
<div class="heute-stats">
|
||
<div class="heute-group">
|
||
<div class="heute-lbl" data-t="todayHeading"></div>
|
||
<div class="heute-inner">
|
||
<div class="stat">
|
||
<div class="slbl" data-t="done2"></div>
|
||
<div class="sval"><span class="sv-tdone"></span><div class="sunit"></div></div>
|
||
</div>
|
||
<div class="stat">
|
||
<div class="slbl" data-t="dailyGoal"></div>
|
||
<div class="sval"><span class="sv-daily"></span><div class="sunit"></div></div>
|
||
</div>
|
||
<div class="stat">
|
||
<div class="slbl" data-t="remaining"></div>
|
||
<div class="sval sv-noch"><span class="sv-st"></span><div class="sunit"></div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="dots-sec">
|
||
<div class="dots-lbl" data-t="history"></div>
|
||
<div class="dots-wrap"></div>
|
||
<div class="legend">
|
||
<span class="leg"><span class="ldot" style="background:rgba(37,99,235,.3)"></span><span data-t="legBuf"></span></span>
|
||
<span class="leg"><span class="ldot" style="background:rgba(22,163,74,.3)"></span><span data-t="legDone"></span></span>
|
||
<span class="leg"><span class="ldot" style="background:rgba(217,119,6,.3)"></span><span data-t="legPartial"></span></span>
|
||
<span class="leg"><span class="ldot" style="background:rgba(220,38,38,.3)"></span><span data-t="legMissed"></span></span>
|
||
</div>
|
||
</div>
|
||
<div class="card-foot"><button class="btn-del" data-t="delGoal"></button></div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-sheet">
|
||
<div class="sheet">
|
||
<div class="shandle"></div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-login">
|
||
<div>
|
||
<div class="stitle" data-t="loginTitle"></div>
|
||
<div class="ssub">Dudi</div>
|
||
<div class="login-err" style="display:none"></div>
|
||
<div class="ff"><label data-t="emailLabel"></label><input class="fi lf-email" type="email" autocomplete="email"/></div>
|
||
<div class="ff"><label data-t="passwordLabel"></label><input class="fi lf-pass" type="password" autocomplete="current-password"/></div>
|
||
<div class="factions"><button class="btn-p lf-sub" data-t="loginBtn"></button></div>
|
||
<div style="text-align:center;margin-top:8px"><button class="btn-lnk lf-fgt" data-t="forgotPw"></button></div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-forgot-pw">
|
||
<div>
|
||
<div class="stitle" data-t="forgotTitle"></div>
|
||
<div class="ssub" data-t="forgotSub"></div>
|
||
<div class="ff"><label data-t="emailLabel"></label><input class="fi fp-email" type="email" autocomplete="email"/></div>
|
||
<div class="login-err" style="display:none"></div>
|
||
<div class="factions">
|
||
<button class="btn-p fp-sub" data-t="sendLink"></button>
|
||
<button class="btn-c fp-back" data-t="back"></button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-email-sent">
|
||
<div>
|
||
<div class="stitle" data-t="emailSentTitle"></div>
|
||
<div class="ssub" data-t="emailSentSub"></div>
|
||
<div class="factions"><button class="btn-p es-ok" data-t="ok"></button></div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-reset-pw">
|
||
<div>
|
||
<div class="stitle" data-t="resetTitle"></div>
|
||
<div class="ff"><label data-t="newPwLabel"></label><input class="fi rp-pass" type="password" autocomplete="new-password" data-ph="min8"/></div>
|
||
<div class="login-err" style="display:none"></div>
|
||
<div class="factions"><button class="btn-p rp-sub" data-t="setPw"></button></div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-pw-changed">
|
||
<div>
|
||
<div class="stitle" data-t="pwChangedTitle"></div>
|
||
<div class="ssub" data-t="pwChangedSub"></div>
|
||
<div class="factions"><button class="btn-p pc-ok" data-t="loginBtn"></button></div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-change-name">
|
||
<div>
|
||
<div class="stitle" data-t="changeNameTitle"></div>
|
||
<div class="ff"><label data-t="yourName"></label><input class="fi cn-name" type="text" autocomplete="name"/></div>
|
||
<div class="login-err" style="display:none"></div>
|
||
<div class="factions">
|
||
<button class="btn-p cn-sub" data-t="save"></button>
|
||
<button class="btn-c cn-can" data-t="cancel"></button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-change-pw">
|
||
<div>
|
||
<div class="stitle" data-t="changePwTitle"></div>
|
||
<div class="ff"><label data-t="currentPwLabel"></label><input class="fi cp-old" type="password" autocomplete="current-password"/></div>
|
||
<div class="ff"><label data-t="newPwLabel"></label><input class="fi cp-new" type="password" autocomplete="new-password" data-ph="min8"/></div>
|
||
<div class="ff"><label data-t="newPwConfLabel"></label><input class="fi cp-new2" type="password" autocomplete="new-password" data-ph="min8"/></div>
|
||
<div class="login-err" style="display:none"></div>
|
||
<div class="factions">
|
||
<button class="btn-p cp-sub" data-t="changePwBtn"></button>
|
||
<button class="btn-c cp-can" data-t="cancel"></button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-register">
|
||
<div>
|
||
<div class="stitle" data-t="registerTitle"></div>
|
||
<div class="ssub" data-t="registerSub"></div>
|
||
<div class="ff"><label data-t="yourName"></label><input class="fi rg-name" type="text" autocomplete="name" data-ph="namePlaceholder"/></div>
|
||
<div class="ff"><label data-t="emailLabel"></label><input class="fi rg-email" type="email" autocomplete="email"/></div>
|
||
<div class="ff"><label data-t="passwordLabel"></label><input class="fi rg-pass" type="password" autocomplete="new-password" data-ph="min8"/></div>
|
||
<div class="ff"><label data-t="pwConfLabel"></label><input class="fi rg-pass2" type="password" autocomplete="new-password" data-ph="pwPlaceholder"/></div>
|
||
<div class="login-err" style="display:none"></div>
|
||
<div class="factions"><button class="btn-p rg-sub" data-t="registerBtn"></button></div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-new-goal">
|
||
<div>
|
||
<div class="stitle" data-t="newGoalTitle"></div>
|
||
<div class="ff"><label data-t="exerciseLabel"></label><input class="fi ng-name" type="text" data-ph="exercisePlaceholder"/></div>
|
||
<div class="fgrid">
|
||
<div class="ff"><label data-t="unitLabel"></label><input class="fi ng-unit" type="text" data-val="unitDefault"/></div>
|
||
<div class="ff"><label data-t="daysLabel"></label><input class="fi ng-days" type="number" min="7" max="365" value="30"/></div>
|
||
</div>
|
||
<div class="fgrid">
|
||
<div class="ff"><label data-t="dailyLabel"></label><input class="fi ng-daily" type="number" min="0.01" step="any" value="50"/></div>
|
||
<div class="ff"><label data-t="weeklyLabel"></label><input class="fi ng-weekly" type="number" min="0.01" step="any" value="350"/></div>
|
||
</div>
|
||
<div class="factions">
|
||
<button class="btn-p ng-sub" data-t="startGoal"></button>
|
||
<button class="btn-c ng-can" data-t="cancel"></button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-data-menu">
|
||
<div>
|
||
<div class="stitle" data-t="dataMenuTitle"></div>
|
||
<div class="ssub" data-t="dataMenuSub"></div>
|
||
<button class="dbtn dm-exp"><span class="dico">⬇</span><span class="dlbl"><span data-t="exportLabel"></span><span class="dsub" data-t="exportSub"></span></span></button>
|
||
<button class="dbtn dm-imp"><span class="dico">⬆</span><span class="dlbl"><span data-t="importLabel"></span><span class="dsub" data-t="importSub"></span></span></button>
|
||
<div class="ddiv"></div>
|
||
<button class="dbtn dm-inv"><span class="dico">🔗</span><span class="dlbl"><span data-t="inviteLabel"></span><span class="dsub" data-t="inviteSub"></span></span></button>
|
||
<button class="dbtn dm-invlist"><span class="dico">📋</span><span class="dlbl"><span data-t="inviteListLabel"></span><span class="dsub" data-t="inviteListSub"></span></span></button>
|
||
<button class="dbtn dm-admin" style="display:none"><span class="dico">👥</span><span class="dlbl" data-t="adminLabel"></span></button>
|
||
<div class="ddiv"></div>
|
||
<button class="dbtn dm-name"><span class="dico">✏️</span><span class="dlbl" data-t="changeName"></span></button>
|
||
<button class="dbtn dm-cpw"><span class="dico">🔑</span><span class="dlbl" data-t="changePw"></span></button>
|
||
<button class="dbtn dm-lgout"><span class="dico">→</span><span class="dlbl" data-t="logout"></span></button>
|
||
<div class="ddiv"></div>
|
||
<div class="lang-row">
|
||
<button class="btn-lang" data-lang="de">DE</button>
|
||
<button class="btn-lang" data-lang="en">EN</button>
|
||
<button class="btn-lang" data-lang="pl">PL</button>
|
||
</div>
|
||
<button class="btn-c dm-cls" style="width:100%;margin-top:4px;text-align:center" data-t="close"></button>
|
||
<div class="ddiv" style="margin-top:16px"></div>
|
||
<button class="dbtn ddanger dm-clr"><span class="dico">✕</span><span class="dlbl"><span data-t="clearAll"></span><span class="dsub" data-t="clearAllSub"></span></span></button>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-invite-form">
|
||
<div>
|
||
<div class="stitle" data-t="inviteFormTitle"></div>
|
||
<div class="ssub" data-t="inviteFormSub"></div>
|
||
<div class="ff"><label data-t="inviteNameLabel"></label><input class="fi inv-name" type="text" data-ph="inviteNamePlaceholder"/></div>
|
||
<div class="factions">
|
||
<button class="btn-p inv-gen" data-t="generateLink"></button>
|
||
<button class="btn-c inv-cancel" data-t="cancel"></button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-invite-link">
|
||
<div>
|
||
<div class="stitle"></div>
|
||
<div class="ssub" data-t="inviteFormSub"></div>
|
||
<div class="ff"><input class="fi il-url" type="text" readonly/></div>
|
||
<div class="factions">
|
||
<button class="btn-p il-copy" data-t="copyLink"></button>
|
||
<button class="btn-c il-close" data-t="close"></button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-invite-list">
|
||
<div>
|
||
<div class="stitle" data-t="inviteListLabel"></div>
|
||
<div class="dpanel-body"></div>
|
||
<div class="factions"><button class="btn-c il-close" data-t="close"></button></div>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-invite-row">
|
||
<div class="set-row">
|
||
<span style="flex:1"><strong class="ir-label"></strong><span class="ir-detail" style="opacity:.6;font-size:.85em"></span></span>
|
||
<button class="ir-copy btn-lnk" style="font-size:.8em;display:none">🔗 <span data-t="linkLabel"></span></button>
|
||
<span class="ir-status" style="font-size:.85em;font-weight:600"></span>
|
||
</div>
|
||
</template>
|
||
|
||
<template id="tpl-admin-users">
|
||
<div>
|
||
<div class="stitle" data-t="adminLabel"></div>
|
||
<div class="dpanel-body" style="overflow-x:auto;padding:0">
|
||
<table style="width:100%;border-collapse:collapse;font-size:13px">
|
||
<thead>
|
||
<tr style="border-bottom:1px solid var(--border)">
|
||
<th style="padding:8px 12px;text-align:left;font-weight:600" data-t="adminColName"></th>
|
||
<th style="padding:8px 12px;text-align:left;font-weight:600" data-t="adminColEmail"></th>
|
||
<th style="padding:8px 12px;text-align:left;font-weight:600;color:var(--text2)" data-t="adminColRegistered"></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody class="au-body"></tbody>
|
||
</table>
|
||
</div>
|
||
<div class="factions"><button class="btn-c au-close" data-t="close"></button></div>
|
||
</div>
|
||
</template>
|
||
|
||
<script src="app.js?v={{ jsv }}"></script>
|
||
</body>
|
||
</html>
|