Kanban: Modal-Scroll auf Mobile (Buttons immer sichtbar), Erstellungsdatum auf Karte

This commit is contained in:
2026-06-24 01:42:30 +02:00
parent 418781f574
commit c2495232cc

View File

@@ -9,7 +9,13 @@ const PRIORITIES = [
{ id: 'high', label: 'Hoch', color: '#ff6b9d' },
];
const COL_COLORS = ['#4ecdc4','#60a5fa','#a78bfa','#ff6b9d','#ffe66d','#fb923c','#4ade80','#f472b6','#94a3b8'];
const prioOf = id => PRIORITIES.find(p => p.id === id) || PRIORITIES[0];
const fmtCardDate = s => {
if (!s) return '';
const d = new Date(String(s).replace(' ', 'T'));
if (isNaN(d)) return '';
return d.toLocaleDateString('de-DE', { day:'2-digit', month:'2-digit', year:'numeric' })
+ ' ' + d.toLocaleTimeString('de-DE', { hour:'2-digit', minute:'2-digit' });
};
// ── Karten-Modal ──────────────────────────────────────────────────────────────
function CardModal({ card, columnId, columns, onSave, onClose, toast }) {
@@ -64,15 +70,22 @@ function CardModal({ card, columnId, columns, onSave, onClose, toast }) {
style={{ position:'fixed',inset:0,background:'rgba(0,0,0,0.7)',zIndex:1000,
display:'flex',alignItems:isMob?'flex-end':'center',justifyContent:'center',padding:isMob?0:20 }}>
<div style={{ background:'#1a1a1e',border:'1px solid rgba(255,255,255,0.12)',
borderRadius:isMob?'16px 16px 0 0':14,padding:'22px 20px 28px',
width:'100%',maxWidth:460 }}>
{isMob && <div style={{ width:36,height:4,background:'rgba(255,255,255,0.15)',borderRadius:2,margin:'0 auto 16px' }}/>}
borderRadius:isMob?'16px 16px 0 0':14,
width:'100%',maxWidth:460,
display:'flex',flexDirection:'column',
maxHeight: isMob ? '92vh' : '90vh',
}}>
{/* Drag-Handle + Header immer sichtbar, nicht scrollend */}
<div style={{ padding:'18px 20px 0', flexShrink:0 }}>
{isMob && <div style={{ width:36,height:4,background:'rgba(255,255,255,0.15)',borderRadius:2,margin:'0 auto 14px' }}/>}
<div style={{ display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:16 }}>
<div style={{ ...S.head, marginBottom:0 }}>{card ? 'KARTE BEARBEITEN' : 'NEUE KARTE'}</div>
<button onClick={onClose} style={{ background:'transparent',border:'none',color:'rgba(255,255,255,0.4)',cursor:'pointer',fontSize:18 }}></button>
</div>
</div>
{/* Scrollbarer Inhalt */}
<div style={{ overflowY:'auto',padding:'0 20px',flex:1,scrollbarWidth:'thin',scrollbarColor:'rgba(255,255,255,0.08) transparent' }}>
<input ref={titleRef} value={title} onChange={e=>setTitle(e.target.value)} onKeyDown={onKey}
placeholder="Titel" style={{ ...S.inp, marginBottom:10 }} />
@@ -83,7 +96,7 @@ function CardModal({ card, columnId, columns, onSave, onClose, toast }) {
{/* Priorität */}
<div style={{ marginBottom:14 }}>
<div style={{ ...S.head, marginBottom:8 }}>PRIORITÄT</div>
<div style={{ display:'flex', gap:6 }}>
<div style={{ display:'flex', gap:6, flexWrap:'wrap' }}>
{PRIORITIES.map(p => (
<button key={p.id} onClick={()=>setPrio(p.id)} style={{
...S.btn(p.color, true),
@@ -95,8 +108,8 @@ function CardModal({ card, columnId, columns, onSave, onClose, toast }) {
</div>
</div>
{/* Verschieben nach (nur bei Bearbeitung sinnvoll, aber auch bei Neu nützlich) */}
<div style={{ marginBottom:18 }}>
{/* Verschieben nach */}
<div style={{ marginBottom:14 }}>
<div style={{ ...S.head, marginBottom:8 }}>{card ? 'VERSCHIEBEN NACH' : 'IN SPALTE'}</div>
{!showNewCol ? (
<div style={{ display:'flex', gap:6, flexWrap:'wrap' }}>
@@ -120,8 +133,11 @@ function CardModal({ card, columnId, columns, onSave, onClose, toast }) {
</div>
)}
</div>
</div>
<div style={{ display:'flex', gap:8, justifyContent:'flex-end' }}>
{/* Aktionsbuttons immer sichtbar am unteren Rand, nicht scrollend */}
<div style={{ padding:'14px 20px 24px', flexShrink:0, borderTop:'1px solid rgba(255,255,255,0.07)',
display:'flex', gap:8, justifyContent:'flex-end' }}>
<button onClick={onClose} style={S.btn('#888888', true)}>Abbrechen</button>
<button onClick={save} disabled={!title.trim()||saving} style={S.btn('#4ecdc4', true)}>
{saving ? '…' : card ? 'Speichern' : 'Erstellen'}
@@ -274,6 +290,14 @@ function KanbanCard({ card, col, allCols, onEdit, onDelete, onMove, isDragging,
{arrowBtn('→', isLastCol, ()=>onMove(card.id, allCols[colIdx+1]?.id))}
</div>
</div>
{/* Erstellungsdatum */}
{card.created_at && (
<div style={{ fontSize:9,fontFamily:'monospace',color:'rgba(255,255,255,0.2)',
marginTop:6, textAlign:'right', letterSpacing:0.5 }}>
{fmtCardDate(card.created_at)}
</div>
)}
</div>
);
}