feat: overlapping event layout and calendar event attachments (#107)
- Overlapping timed events in week/day views now render side-by-side using a column-layout algorithm - Calendar events support optional file attachments (images, PDFs, documents up to 5 MB) - Attachment images shown in event popup; other files as download links - Birthday modal redesigned with photo/avatar side-by-side with name/date fields - DB migration 27: adds attachment_name, attachment_mime, attachment_size, attachment_data columns to calendar_events - Server-side MIME allowlist and size validation for attachments - i18n: all 15 locales include new attachment keys (de properly translated) Co-Authored-By: Rafael Foster <rafaelfoster@users.noreply.github.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -287,6 +287,21 @@
|
||||
background: color-mix(in srgb, var(--module-accent) 16%, white);
|
||||
}
|
||||
|
||||
.birthday-avatar-editor {
|
||||
width: 84px;
|
||||
height: 84px;
|
||||
margin: 0 auto var(--space-3);
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: var(--radius-full);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: color-mix(in srgb, var(--module-accent) 16%, white);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.birthday-preview__image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -300,7 +315,51 @@
|
||||
}
|
||||
|
||||
.birthday-modal__photo-actions {
|
||||
margin-top: var(--space-2);
|
||||
display: flex;
|
||||
gap: var(--space-2);
|
||||
justify-content: center;
|
||||
margin-top: calc(var(--space-1) * -1);
|
||||
margin-bottom: var(--space-2);
|
||||
}
|
||||
|
||||
.birthday-modal__photo-action {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: var(--radius-full);
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-surface);
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.birthday-modal__photo-action svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.birthday-modal__photo-action--danger {
|
||||
color: var(--color-danger);
|
||||
}
|
||||
|
||||
.birthday-modal__identity {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
.birthday-modal__photo-wrap {
|
||||
width: 84px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.birthday-modal__fields {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.birthday-modal__hint {
|
||||
@@ -308,6 +367,16 @@
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.birthday-modal__identity {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.birthday-modal__photo-actions {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.birthdays-grid {
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
@@ -391,8 +391,6 @@
|
||||
|
||||
.week-event {
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
right: 2px;
|
||||
border-radius: var(--radius-xs);
|
||||
padding: var(--space-0h) var(--space-1);
|
||||
font-size: var(--text-xs);
|
||||
@@ -424,6 +422,29 @@
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.event-attachment-preview {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-2);
|
||||
margin-top: var(--space-2);
|
||||
}
|
||||
|
||||
.event-attachment-preview img {
|
||||
width: 100%;
|
||||
max-height: 180px;
|
||||
object-fit: cover;
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
}
|
||||
|
||||
.event-attachment-preview a {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
color: var(--color-accent);
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------
|
||||
* Tagesansicht
|
||||
* -------------------------------------------------------- */
|
||||
@@ -768,6 +789,25 @@
|
||||
border-top: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.event-popup__attachment {
|
||||
margin-top: var(--space-2);
|
||||
}
|
||||
|
||||
.event-popup__attachment--image img {
|
||||
width: 100%;
|
||||
max-height: 220px;
|
||||
object-fit: cover;
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
}
|
||||
|
||||
.event-popup__attachment--file {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------
|
||||
* Ganztägige Ereignisse (oben in Wochen-/Tagesansicht)
|
||||
* -------------------------------------------------------- */
|
||||
|
||||
Reference in New Issue
Block a user