{ api('/dashboard/links').then(setLinks).catch(() => {}); }, []);
+ const getFavicon = url => {
+ try { return `https://www.google.com/s2/favicons?sz=64&domain=${new URL(url).hostname}`; }
+ catch { return null; }
+ };
+
const save = async () => {
if (!form.title.trim() || !form.url.trim()) { toast('Titel und URL erforderlich', 'error'); return; }
let url = form.url.trim();
if (!/^https?:\/\//i.test(url)) url = 'https://' + url;
+ // Auto favicon if user left default
+ const icon = form.icon === '🔗' ? (getFavicon(url) || '🔗') : form.icon;
try {
if (editId) {
- const u = await api(`/dashboard/links/${editId}`, { method:'PUT', body:{...form, url} });
+ const u = await api(`/dashboard/links/${editId}`, { method:'PUT', body:{...form, icon, url} });
setLinks(p => p.map(l => l.id===editId ? u : l));
} else {
- const n = await api('/dashboard/links', { body:{...form, url} });
+ const n = await api('/dashboard/links', { body:{...form, icon, url} });
setLinks(p => [...p, n]);
}
toast(editId ? 'Aktualisiert' : 'Gespeichert');
@@ -370,7 +388,7 @@ function QuickLinks({ toast, mobile }) {
SCHNELLZUGRIFF
{editMode && }
-
@@ -396,7 +414,9 @@ function QuickLinks({ toast, mobile }) {
padding:'10px 14px', background:'rgba(255,255,255,0.04)',
border:'1px solid rgba(255,255,255,0.08)', borderRadius:10,
textDecoration:'none', minWidth:60, cursor:editMode ? 'default' : 'pointer' }}>
- {l.icon}
+ {l.icon && l.icon.startsWith('http')
+ ?
e.target.style.display='none'}/>
+ : {l.icon}}
{l.title}
@@ -568,7 +588,7 @@ function BestellStats() {
- STATISTIK
+ 3D-DRUCK STATISTIK
▶
@@ -640,6 +660,7 @@ const Field = ({ label, type='text', value, onChange, placeholder='', autoCapita
function AdminPanel({ toast, mobile }) {
const [pw, setPw] = useState({ current:'', newPw:'', confirm:'' });
+ const [avatar, setAvatar] = useState(localStorage.getItem('dd_avatar') || null);
const [un, setUn] = useState({ newUsername:'', unPw:'' });
const [file, setFile] = useState(null);
const [busy, setBusy] = useState({ pw:false, un:false, restore:false });
@@ -690,6 +711,41 @@ function AdminPanel({ toast, mobile }) {
Admin
+
+
+
+ {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 && {setAvatar(null);localStorage.removeItem('dd_avatar');toast('Avatar entfernt');}}
+ style={{...S.btn('#ff6b9d',true)}}>✕ Entfernen}
+
+
setUn(p=>({...p,newUsername:e.target.value}))} />
setUn(p=>({...p,unPw:e.target.value}))} />