Dashboard
-
+
{new Date().toLocaleDateString('de-DE', { weekday:'long', day:'numeric', month:'long' })}
Einstellungen
- {/* Subnavigation */}
{[['profil','Profil'],['backup','Backup']].map(([k,l]) => (
))}
- {section === 'profil' &&
-
-
-
- {avatar
- ?

- :
}
-
-
-
- {
- const file = e.target.files?.[0]; if(!file) return;
- const reader = new FileReader();
- reader.onload = ev => {
- const canvas = document.createElement('canvas');
- const img = new Image(); img.onload = () => {
- const size = 120;
- canvas.width = size; canvas.height = size;
- const ctx = canvas.getContext('2d');
- ctx.beginPath(); ctx.arc(size/2,size/2,size/2,0,Math.PI*2);
- ctx.clip();
- const min = Math.min(img.width,img.height);
- ctx.drawImage(img,(img.width-min)/2,(img.height-min)/2,min,min,0,0,size,size);
- const data = canvas.toDataURL('image/jpeg',0.85);
- setAvatar(data); localStorage.setItem('dd_avatar',data); toast('Avatar gespeichert');
- }; img.src = ev.target.result;
- }; reader.readAsDataURL(file);
- }} style={{...S.inp,fontSize:13,padding:'7px 10px',cursor:'pointer'}}/>
-
+ {section === 'profil' && (
+
+
+
+
+ {avatar
+ ?

+ :
}
+
+
+
+ {
+ const file = e.target.files?.[0]; if(!file) return;
+ const reader = new FileReader();
+ reader.onload = ev => {
+ const canvas = document.createElement('canvas');
+ const img = new Image(); img.onload = () => {
+ const size = 120;
+ canvas.width = size; canvas.height = size;
+ const ctx = canvas.getContext('2d');
+ ctx.beginPath(); ctx.arc(size/2,size/2,size/2,0,Math.PI*2);
+ ctx.clip();
+ const min = Math.min(img.width,img.height);
+ ctx.drawImage(img,(img.width-min)/2,(img.height-min)/2,min,min,0,0,size,size);
+ const data = canvas.toDataURL('image/jpeg',0.85);
+ setAvatar(data); localStorage.setItem('dd_avatar',data); toast('Avatar gespeichert');
+ }; img.src = ev.target.result;
+ }; reader.readAsDataURL(file);
+ }} style={{...S.inp,fontSize:13,padding:'7px 10px',cursor:'pointer'}}/>
+
+
+ {avatar && }
+
+
+ setUn(p=>({...p,newUsername:e.target.value}))} />
+ setUn(p=>({...p,unPw:e.target.value}))} />
+
+
+
+ setPw(p=>({...p,current:e.target.value}))} />
+ setPw(p=>({...p,newPw:e.target.value}))} />
+ setPw(p=>({...p,confirm:e.target.value}))} />
+
+
- {avatar &&
}
-
+ )}
-
- setUn(p=>({...p,newUsername:e.target.value}))} />
- setUn(p=>({...p,unPw:e.target.value}))} />
-
-
-
-
- setPw(p=>({...p,current:e.target.value}))} />
- setPw(p=>({...p,newPw:e.target.value}))} />
- setPw(p=>({...p,confirm:e.target.value}))} />
-
-
-
-
}
-
- {section === 'backup' &&
-
-
- Vollständige SQLite-Datenbank sichern oder wiederherstellen.
-
-
-
-
-
setFile(e.target.files[0])}
- style={{ ...S.inp, flex:1, padding:'9px 10px', cursor:'pointer', fontSize:13 }} />
-
+ {section === 'backup' && (
+
+
+
+ Vollständige SQLite-Datenbank sichern oder wiederherstellen.
+
+
+
+
+ setFile(e.target.files[0])}
+ style={{ ...S.inp, flex:1, padding:'9px 10px', cursor:'pointer', fontSize:13 }} />
+
+
+ {file && {file.name}
}
+
- {file &&
{file.name}
}
-
-
}
+ )}
);
}
@@ -816,6 +844,7 @@ function AdminPanel({ toast, mobile }) {
// ── App Shell ─────────────────────────────────────────────────────────────────
export default function App() {
const mobile = useIsMobile();
+ const [splash, setSplash] = useState(() => window.matchMedia('(display-mode: standalone)').matches);
const [user,setUser]=useState(null);
const [active,setActive]=useState('dashboard');
const [toastMsg,setToastMsg]=useState({msg:'',type:'success'});
@@ -844,6 +873,7 @@ export default function App() {
setTimeout(()=>setToastMsg({msg:'',type:'success'}),3500);
},[]);
+ if(splash) return setSplash(false)}/>;
if(!user) return setUser(u)}/>;
const activeTool = TOOLS.find(t=>t.id===active);