Design: Rest aus P1 - Archivieren als roter Link, Planboard-Tokens und Scroll-Container, !important entfernt, Invalid-Ring im Fokus, Schublade nicht tabbar, Dialog-Fokus, Protokoll ohne Ueberlauf
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f911dbcb03
commit
8d75f7346e
6 files changed
+98
-91
No files matched your search
+13
-12
@@ -277,29 +277,30 @@
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.admin-status,
|
||||
.admin-role {
|
||||
display: inline-flex !important;
|
||||
/* Tabellenzellen: .admin-table td > span (0,1,2) setzt display/Farbe/Schrift; die Selektoren hier sind spezifischer (0,2,1) */
|
||||
.admin-table td > .admin-status,
|
||||
.admin-table td > .admin-role {
|
||||
display: inline-flex;
|
||||
width: fit-content;
|
||||
align-items: center;
|
||||
padding: 3px 7px;
|
||||
border: 1px solid var(--admin-line-strong);
|
||||
border-radius: 4px;
|
||||
color: var(--text-muted) !important;
|
||||
font-size: 11px !important;
|
||||
color: var(--text-muted);
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.admin-status.active,
|
||||
.admin-role.admin {
|
||||
border-color: rgba(16, 185, 129, 0.45);
|
||||
color: #6ee7b7 !important;
|
||||
.admin-table td > .admin-status.active,
|
||||
.admin-table td > .admin-role.admin {
|
||||
border-color: var(--green-fg);
|
||||
color: var(--green-fg);
|
||||
}
|
||||
|
||||
.admin-shortcode {
|
||||
color: var(--text) !important;
|
||||
.admin-table td > .admin-shortcode {
|
||||
color: var(--text);
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||
font-size: 12px !important;
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
|
||||
+70
-67
@@ -11,10 +11,11 @@ import { groupAppointmentsByDay, countInRange, dayKey } from '../lib/planboard'
|
||||
/* Termine haengen an den Tickets (startDate/startTime/endTime/assignedTo);
|
||||
die Aufbereitung steckt in src/lib/planboard.js. */
|
||||
|
||||
// Farben nur ueber Tokens (P3 baut die Seite um)
|
||||
const TYPE_COLORS = {
|
||||
akquise: { bg: 'rgba(198,113,57,0.16)', fg: '#c67139' },
|
||||
webpage: { bg: 'rgba(122,138,94,0.18)', fg: '#7a8a5e' },
|
||||
project: { bg: 'rgba(122,138,94,0.18)', fg: '#7a8a5e' },
|
||||
akquise: { bg: 'var(--appt-akquise)', fg: 'var(--orange-fg)' },
|
||||
webpage: { bg: 'var(--bg-hover)', fg: 'var(--text-2)' },
|
||||
project: { bg: 'var(--bg-hover)', fg: 'var(--text-2)' },
|
||||
}
|
||||
|
||||
export default function PlanboardPage() {
|
||||
@@ -47,72 +48,74 @@ export default function PlanboardPage() {
|
||||
}
|
||||
/>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 12 }}>
|
||||
{weekDays.map((day) => {
|
||||
const entries = byDay[dayKey(day)] || []
|
||||
const today = isSameDay(day, new Date())
|
||||
return (
|
||||
<Card key={day.toISOString()} pad={false}>
|
||||
<div style={{
|
||||
padding: '10px 12px',
|
||||
borderBottom: '1px solid var(--border)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
background: today ? 'rgba(198,113,57,0.10)' : undefined,
|
||||
}}>
|
||||
<strong style={{ fontSize: 13 }}>{format(day, 'EEEE', { locale: de })}</strong>
|
||||
<span className="faint" style={{ fontSize: 12 }}>{format(day, 'dd.MM')}</span>
|
||||
</div>
|
||||
<div className="planboard-scroll">
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 12 }}>
|
||||
{weekDays.map((day) => {
|
||||
const entries = byDay[dayKey(day)] || []
|
||||
const today = isSameDay(day, new Date())
|
||||
return (
|
||||
<Card key={day.toISOString()} pad={false}>
|
||||
<div style={{
|
||||
padding: '10px 12px',
|
||||
borderBottom: '1px solid var(--border)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
background: today ? 'var(--appt-akquise)' : undefined,
|
||||
}}>
|
||||
<strong style={{ fontSize: 13 }}>{format(day, 'EEEE', { locale: de })}</strong>
|
||||
<span className="muted" style={{ fontSize: 12 }}>{format(day, 'dd.MM')}</span>
|
||||
</div>
|
||||
|
||||
<div style={{ padding: 8, minHeight: 120, display: 'flex', flexDirection: 'column', gap: 6 }}>
|
||||
{entries.length === 0 && (
|
||||
<p className="faint" style={{ fontSize: 12, padding: '4px 4px 0' }}>Keine Termine</p>
|
||||
)}
|
||||
<div style={{ padding: 8, minHeight: 120, display: 'flex', flexDirection: 'column', gap: 6 }}>
|
||||
{entries.length === 0 && (
|
||||
<p className="faint" style={{ fontSize: 12, padding: '4px 4px 0' }}>Keine Termine</p>
|
||||
)}
|
||||
|
||||
{entries.map((entry) => {
|
||||
const color = TYPE_COLORS[String(entry.type).toLowerCase()]
|
||||
|| { bg: 'rgba(127,127,127,0.10)', fg: 'var(--border)' }
|
||||
return (
|
||||
<button
|
||||
key={entry.id}
|
||||
type="button"
|
||||
title={`Ticket #${entry.woid} öffnen`}
|
||||
onClick={() => navigate(`/tickets?woid=${encodeURIComponent(entry.woid)}`)}
|
||||
style={{
|
||||
textAlign: 'left',
|
||||
border: '1px solid var(--border)',
|
||||
borderLeft: `3px solid ${color.fg}`,
|
||||
borderRadius: 8,
|
||||
background: color.bg,
|
||||
color: 'inherit',
|
||||
padding: '8px 10px',
|
||||
cursor: 'pointer',
|
||||
font: 'inherit',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
}}
|
||||
>
|
||||
<span style={{ fontSize: 12, fontWeight: 700 }}>
|
||||
{entry.time ? `${entry.time}${entry.endTime ? `–${entry.endTime}` : ''}` : 'ohne Uhrzeit'}
|
||||
</span>
|
||||
<span style={{ fontSize: 12.5, fontWeight: 600, lineHeight: 1.25 }}>
|
||||
{entry.customerName || entry.topic}
|
||||
</span>
|
||||
{entry.customerName && (
|
||||
<span className="faint" style={{ fontSize: 11.5, lineHeight: 1.25 }}>{entry.topic}</span>
|
||||
)}
|
||||
<span className="faint" style={{ fontSize: 11 }}>
|
||||
#{entry.woid}
|
||||
{entry.employeeName ? ` · ${entry.employeeShort || entry.employeeName}` : ' · niemand zugewiesen'}
|
||||
</span>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
)
|
||||
})}
|
||||
{entries.map((entry) => {
|
||||
const color = TYPE_COLORS[String(entry.type).toLowerCase()]
|
||||
|| { bg: 'var(--bg-subtle)', fg: 'var(--line-strong)' }
|
||||
return (
|
||||
<button
|
||||
key={entry.id}
|
||||
type="button"
|
||||
title={`Ticket #${entry.woid} öffnen`}
|
||||
onClick={() => navigate(`/tickets?woid=${encodeURIComponent(entry.woid)}`)}
|
||||
style={{
|
||||
textAlign: 'left',
|
||||
border: '1px solid var(--border)',
|
||||
borderLeft: `3px solid ${color.fg}`,
|
||||
borderRadius: 8,
|
||||
background: color.bg,
|
||||
color: 'inherit',
|
||||
padding: '8px 10px',
|
||||
cursor: 'pointer',
|
||||
font: 'inherit',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
}}
|
||||
>
|
||||
<span style={{ fontSize: 12, fontWeight: 700 }}>
|
||||
{entry.time ? `${entry.time}${entry.endTime ? `–${entry.endTime}` : ''}` : 'ohne Uhrzeit'}
|
||||
</span>
|
||||
<span style={{ fontSize: 12.5, fontWeight: 600, lineHeight: 1.25 }}>
|
||||
{entry.customerName || entry.topic}
|
||||
</span>
|
||||
{entry.customerName && (
|
||||
<span className="muted" style={{ fontSize: 11.5, lineHeight: 1.25 }}>{entry.topic}</span>
|
||||
)}
|
||||
<span className="muted" style={{ fontSize: 11 }}>
|
||||
#{entry.woid}
|
||||
{entry.employeeName ? ` · ${entry.employeeShort || entry.employeeName}` : ' · niemand zugewiesen'}
|
||||
</span>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -743,8 +743,7 @@ export default function ProjectsPage() {
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: '8px', marginTop: '16px', flexWrap: 'wrap' }}>
|
||||
<button
|
||||
type="button"
|
||||
className="btn"
|
||||
style={{ background: editProject.archived ? 'var(--accent)' : 'var(--danger)', color: '#fff' }}
|
||||
className={editProject.archived ? 'btn' : 'link-danger'}
|
||||
onClick={() => handleArchiveToggle(editProject)}
|
||||
disabled={archiveBusy || editLoading}
|
||||
>
|
||||
|
||||
Reference in new issue
Block a user