22ec13e559
* Adding flexible reminder options to birthdays * Fix database migration merge conflict * Truncate calendar popup descriptions * Log app version on backend startup * Add host-mounted data and backup folders * feat: add housekeeping module * fix: align housekeeping UI and add task creation * refactor: rebuild housekeeping experience * feat: support multiple housekeeping staff * feat: integrate housekeeping visits with calendar * feat: refine housekeeping visits and payments * feat: add housekeeping staff visit logs * feat: add housekeeping receipts and document folders * feat: localize housekeeping folders and chores * feat: refine housekeeping tabs and document folders * fix: sync housekeeping tab active state * feat: use configured app name in onboarding and manifest
679 lines
14 KiB
CSS
679 lines
14 KiB
CSS
.housekeeping-page {
|
|
--module-accent: var(--module-housekeeping);
|
|
max-width: var(--content-max-width);
|
|
min-height: 100%;
|
|
margin: 0 auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.housekeeping-toolbar {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, auto) minmax(0, 1fr);
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: var(--space-2);
|
|
padding: var(--space-3) var(--space-4);
|
|
border-top: 3px solid var(--module-accent);
|
|
border-bottom: 1px solid var(--color-border);
|
|
background-color: color-mix(in srgb, var(--color-surface) 90%, transparent);
|
|
backdrop-filter: var(--blur-sm);
|
|
-webkit-backdrop-filter: var(--blur-sm);
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: var(--z-sticky);
|
|
}
|
|
|
|
.housekeeping-toolbar__title {
|
|
font-size: var(--text-lg);
|
|
font-weight: var(--font-weight-bold);
|
|
min-width: 0;
|
|
}
|
|
|
|
.housekeeping-check-small {
|
|
min-height: var(--target-lg);
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.housekeeping-check-small:disabled {
|
|
background: var(--color-surface-3);
|
|
color: var(--color-text-disabled);
|
|
border-color: var(--color-border);
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.housekeeping-tabs {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
gap: var(--space-1);
|
|
height: var(--kitchen-tabs-height, var(--sub-tabs-height));
|
|
padding: 0;
|
|
background: transparent;
|
|
border-bottom: 0;
|
|
overflow-x: auto;
|
|
scrollbar-width: none;
|
|
}
|
|
|
|
.housekeeping-tabs::-webkit-scrollbar { display: none; }
|
|
|
|
.housekeeping-tab {
|
|
--active-module-accent: var(--module-accent);
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.housekeeping-tab[aria-current="page"] {
|
|
background-color: color-mix(in srgb, var(--module-accent) 14%, transparent);
|
|
color: var(--module-accent);
|
|
}
|
|
|
|
.housekeeping-content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-4);
|
|
padding: var(--space-4);
|
|
padding-bottom: calc(var(--space-16) + env(safe-area-inset-bottom));
|
|
}
|
|
|
|
.housekeeping-card,
|
|
.housekeeping-worker-strip,
|
|
.housekeeping-metric,
|
|
.housekeeping-task,
|
|
.housekeeping-report-item {
|
|
background: var(--color-surface);
|
|
border: 1.5px solid var(--color-border);
|
|
border-radius: var(--radius-md);
|
|
}
|
|
|
|
.housekeeping-card {
|
|
border-top: 3px solid var(--module-accent);
|
|
padding: var(--space-4);
|
|
}
|
|
|
|
.housekeeping-card h2 {
|
|
margin: 0 0 var(--space-3);
|
|
font-size: var(--text-lg);
|
|
font-weight: var(--font-weight-bold);
|
|
letter-spacing: 0;
|
|
}
|
|
|
|
.housekeeping-worker-strip {
|
|
display: grid;
|
|
grid-template-columns: 48px minmax(0, 1fr) auto;
|
|
align-items: center;
|
|
gap: var(--space-3);
|
|
padding: var(--space-3);
|
|
}
|
|
|
|
.housekeeping-worker-stack,
|
|
.housekeeping-staff-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-3);
|
|
}
|
|
|
|
.housekeeping-worker-strip div:last-child {
|
|
display: grid;
|
|
gap: 2px;
|
|
min-width: 0;
|
|
}
|
|
|
|
.housekeeping-worker-strip span,
|
|
.housekeeping-muted {
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
.housekeeping-avatar {
|
|
width: 48px;
|
|
height: 48px;
|
|
border-radius: var(--radius-full);
|
|
color: var(--color-text-on-accent);
|
|
display: grid;
|
|
place-items: center;
|
|
font-weight: var(--font-weight-bold);
|
|
overflow: hidden;
|
|
border: 1px solid var(--color-border);
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.housekeeping-avatar img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.housekeeping-avatar--lg {
|
|
width: 96px;
|
|
height: 96px;
|
|
border: 0;
|
|
font-size: var(--text-xl);
|
|
}
|
|
|
|
.housekeeping-worker-empty {
|
|
display: flex;
|
|
gap: var(--space-3);
|
|
align-items: center;
|
|
}
|
|
|
|
.housekeeping-worker-empty svg {
|
|
width: 32px;
|
|
height: 32px;
|
|
color: var(--module-accent);
|
|
}
|
|
|
|
.housekeeping-worker-empty p {
|
|
margin: 0;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
.housekeeping-metrics {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: var(--space-3);
|
|
}
|
|
|
|
.housekeeping-metrics--compact {
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
margin-top: var(--space-3);
|
|
}
|
|
|
|
.housekeeping-metric {
|
|
min-height: 104px;
|
|
padding: var(--space-3);
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.housekeeping-metric span,
|
|
.housekeeping-section-heading span {
|
|
color: var(--color-text-secondary);
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
.housekeeping-metric strong {
|
|
font-size: var(--text-xl);
|
|
line-height: 1.15;
|
|
letter-spacing: 0;
|
|
}
|
|
|
|
.housekeeping-section-heading {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: baseline;
|
|
gap: var(--space-3);
|
|
margin-bottom: var(--space-3);
|
|
}
|
|
|
|
.housekeeping-section-heading h2 {
|
|
margin: 0;
|
|
}
|
|
|
|
.housekeeping-chart {
|
|
min-height: 126px;
|
|
display: flex;
|
|
align-items: end;
|
|
gap: var(--space-3);
|
|
overflow-x: auto;
|
|
padding-top: var(--space-3);
|
|
}
|
|
|
|
.housekeeping-chart__bar-wrap {
|
|
min-width: 44px;
|
|
display: grid;
|
|
justify-items: center;
|
|
gap: var(--space-2);
|
|
color: var(--color-text-secondary);
|
|
font-size: var(--text-xs);
|
|
}
|
|
|
|
.housekeeping-chart__bar {
|
|
width: 24px;
|
|
border-radius: var(--radius-full) var(--radius-full) 0 0;
|
|
background: var(--module-accent);
|
|
}
|
|
|
|
.housekeeping-field {
|
|
display: grid;
|
|
gap: var(--space-2);
|
|
font-weight: var(--font-weight-semibold);
|
|
}
|
|
|
|
.housekeeping-field input,
|
|
.housekeeping-field textarea,
|
|
.housekeeping-field select {
|
|
width: 100%;
|
|
min-height: var(--target-lg);
|
|
border: 1.5px solid var(--color-border);
|
|
border-radius: var(--radius-sm);
|
|
background: var(--color-surface);
|
|
color: var(--color-text-primary);
|
|
font: inherit;
|
|
font-size: var(--text-base);
|
|
padding: 0 var(--space-3);
|
|
}
|
|
|
|
.housekeeping-field textarea {
|
|
min-height: 120px;
|
|
padding: var(--space-3);
|
|
resize: vertical;
|
|
}
|
|
|
|
.housekeeping-field--inline {
|
|
min-width: 180px;
|
|
}
|
|
|
|
.housekeeping-field--color input {
|
|
padding: var(--space-1);
|
|
}
|
|
|
|
.housekeeping-task-form,
|
|
.housekeeping-report-form,
|
|
.housekeeping-worker-form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-3);
|
|
}
|
|
|
|
.housekeeping-form-grid {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 132px;
|
|
gap: var(--space-3);
|
|
align-items: end;
|
|
}
|
|
|
|
.housekeeping-form-grid--wide {
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
}
|
|
|
|
.housekeeping-form-submit {
|
|
min-height: var(--target-lg);
|
|
align-self: flex-start;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
.housekeeping-template-list {
|
|
display: flex;
|
|
gap: var(--space-2);
|
|
overflow-x: auto;
|
|
padding-bottom: var(--space-1);
|
|
}
|
|
|
|
.housekeeping-template {
|
|
min-width: 180px;
|
|
border: 1.5px dashed var(--color-border);
|
|
border-radius: var(--radius-md);
|
|
background: var(--color-surface);
|
|
color: var(--color-text-primary);
|
|
padding: var(--space-3);
|
|
text-align: left;
|
|
display: grid;
|
|
gap: var(--space-1);
|
|
}
|
|
|
|
.housekeeping-template small {
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
.housekeeping-task-list,
|
|
.housekeeping-reports {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-3);
|
|
}
|
|
|
|
.housekeeping-task {
|
|
display: grid;
|
|
grid-template-columns: 56px 1fr;
|
|
gap: var(--space-3);
|
|
align-items: center;
|
|
min-height: 88px;
|
|
padding: var(--space-3);
|
|
border-left: 6px solid var(--color-success);
|
|
}
|
|
|
|
.housekeeping-task--today {
|
|
border-left-color: var(--color-warning);
|
|
}
|
|
|
|
.housekeeping-task--overdue {
|
|
border-left-color: var(--color-danger);
|
|
}
|
|
|
|
.housekeeping-task__check {
|
|
width: 52px;
|
|
height: 52px;
|
|
border: 2px solid var(--module-accent);
|
|
border-radius: var(--radius-full);
|
|
background: color-mix(in srgb, var(--module-accent) 10%, var(--color-surface));
|
|
color: var(--module-accent);
|
|
display: grid;
|
|
place-items: center;
|
|
}
|
|
|
|
.housekeeping-task__body h2 {
|
|
margin: 0;
|
|
font-size: var(--text-base);
|
|
letter-spacing: 0;
|
|
}
|
|
|
|
.housekeeping-task__body p {
|
|
margin: var(--space-1) 0;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
.housekeeping-task__body span {
|
|
font-weight: var(--font-weight-bold);
|
|
}
|
|
|
|
.housekeeping-empty,
|
|
.housekeeping-loading {
|
|
min-height: 180px;
|
|
display: grid;
|
|
place-items: center;
|
|
text-align: center;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
.housekeeping-empty svg {
|
|
width: 44px;
|
|
height: 44px;
|
|
color: var(--module-accent);
|
|
}
|
|
|
|
.housekeeping-photo {
|
|
min-height: 72px;
|
|
border: 1.5px dashed color-mix(in srgb, var(--module-accent) 55%, var(--color-border));
|
|
border-radius: var(--radius-md);
|
|
color: var(--module-accent);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--space-2);
|
|
font-weight: var(--font-weight-semibold);
|
|
}
|
|
|
|
.housekeeping-photo input {
|
|
position: absolute;
|
|
inline-size: 1px;
|
|
block-size: 1px;
|
|
opacity: 0;
|
|
}
|
|
|
|
.housekeeping-photo-preview {
|
|
width: 100%;
|
|
max-height: 260px;
|
|
object-fit: cover;
|
|
border-radius: var(--radius-md);
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
.housekeeping-report-item {
|
|
display: grid;
|
|
grid-template-columns: 56px 1fr;
|
|
gap: var(--space-3);
|
|
align-items: center;
|
|
padding: var(--space-3);
|
|
}
|
|
|
|
.housekeeping-report-item--visit {
|
|
grid-template-columns: 48px minmax(0, 1fr) auto;
|
|
}
|
|
|
|
.housekeeping-report-item--visit .housekeeping-avatar img {
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: inherit;
|
|
background: transparent;
|
|
}
|
|
|
|
.housekeeping-report-item img,
|
|
.housekeeping-report-item > svg {
|
|
width: 56px;
|
|
height: 56px;
|
|
border-radius: var(--radius-sm);
|
|
object-fit: cover;
|
|
color: var(--module-accent);
|
|
background: color-mix(in srgb, var(--module-accent) 10%, var(--color-surface));
|
|
}
|
|
|
|
.housekeeping-report-item div {
|
|
display: grid;
|
|
gap: 3px;
|
|
}
|
|
|
|
.housekeeping-report-item span {
|
|
color: var(--color-text-secondary);
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
.housekeeping-report-modal {
|
|
display: grid;
|
|
gap: var(--space-4);
|
|
}
|
|
|
|
.housekeeping-report-details {
|
|
display: grid;
|
|
gap: var(--space-3);
|
|
margin: 0;
|
|
}
|
|
|
|
.housekeeping-report-details div {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
gap: var(--space-3);
|
|
padding-bottom: var(--space-2);
|
|
border-bottom: 1px solid var(--color-border);
|
|
}
|
|
|
|
.housekeeping-report-details dt {
|
|
color: var(--color-text-secondary);
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
.housekeeping-report-details dd {
|
|
margin: 0;
|
|
font-weight: var(--font-weight-semibold);
|
|
text-align: right;
|
|
}
|
|
|
|
.housekeeping-staff-row {
|
|
display: grid;
|
|
grid-template-columns: 48px 1fr auto;
|
|
gap: var(--space-3);
|
|
align-items: center;
|
|
padding: var(--space-3);
|
|
border: 1.5px solid var(--color-border);
|
|
border-radius: var(--radius-md);
|
|
background: var(--color-surface);
|
|
}
|
|
|
|
.housekeeping-staff-row[role="button"] {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.housekeeping-staff-row[role="button"]:hover,
|
|
.housekeeping-staff-row[role="button"]:focus-visible,
|
|
.housekeeping-staff-row--active {
|
|
border-color: var(--module-accent);
|
|
background: color-mix(in srgb, var(--module-accent) 8%, var(--color-surface));
|
|
}
|
|
|
|
.housekeeping-staff-row div:nth-child(2) {
|
|
display: grid;
|
|
gap: 2px;
|
|
min-width: 0;
|
|
}
|
|
|
|
.housekeeping-staff-row span {
|
|
color: var(--color-text-secondary);
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
.housekeeping-profile-editor {
|
|
display: grid;
|
|
grid-template-columns: auto 1fr;
|
|
gap: var(--space-4);
|
|
align-items: center;
|
|
}
|
|
|
|
.housekeeping-profile-editor__fields {
|
|
display: grid;
|
|
gap: var(--space-3);
|
|
}
|
|
|
|
.housekeeping-staff-log {
|
|
margin-top: var(--space-3);
|
|
}
|
|
|
|
.housekeeping-staff-log-list {
|
|
display: grid;
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
.housekeeping-staff-log-row {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr) auto;
|
|
gap: var(--space-3);
|
|
align-items: center;
|
|
padding: var(--space-3);
|
|
border: 1.5px solid var(--color-border);
|
|
border-radius: var(--radius-md);
|
|
background: var(--color-surface);
|
|
}
|
|
|
|
.housekeeping-staff-log-row > div:first-child {
|
|
display: grid;
|
|
gap: 2px;
|
|
min-width: 0;
|
|
}
|
|
|
|
.housekeeping-staff-log-row span {
|
|
color: var(--color-text-secondary);
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
.housekeeping-staff-log-row__actions {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
.housekeeping-log-action {
|
|
min-height: var(--target-sm);
|
|
padding-inline: var(--space-3);
|
|
gap: var(--space-2);
|
|
}
|
|
|
|
.housekeeping-log-action svg {
|
|
width: 17px;
|
|
height: 17px;
|
|
}
|
|
|
|
.modal-panel .document-dropzone {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--space-2);
|
|
min-height: 132px;
|
|
padding: var(--space-4);
|
|
border: 1.5px dashed color-mix(in srgb, var(--module-accent) 48%, var(--color-border));
|
|
border-radius: var(--radius-md);
|
|
background: color-mix(in srgb, var(--module-accent) 7%, var(--color-surface));
|
|
color: var(--color-text-secondary);
|
|
text-align: center;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.modal-panel .document-dropzone__icon {
|
|
width: 42px;
|
|
height: 42px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: var(--radius-md);
|
|
color: var(--module-accent);
|
|
background: var(--color-surface);
|
|
box-shadow: var(--shadow-sm);
|
|
}
|
|
|
|
.modal-panel .document-dropzone__title {
|
|
font-size: var(--text-sm);
|
|
font-weight: var(--font-weight-semibold);
|
|
color: var(--color-text-primary);
|
|
}
|
|
|
|
.modal-panel .document-dropzone__hint,
|
|
.modal-panel .document-dropzone__file {
|
|
max-width: 100%;
|
|
font-size: var(--text-xs);
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.modal-panel .document-dropzone__file {
|
|
padding: var(--space-1) var(--space-2);
|
|
border-radius: var(--radius-sm);
|
|
color: var(--module-accent);
|
|
background: color-mix(in srgb, var(--module-accent) 14%, transparent);
|
|
font-weight: var(--font-weight-semibold);
|
|
}
|
|
|
|
@media (max-width: 720px) {
|
|
.housekeeping-toolbar {
|
|
grid-template-columns: 1fr;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.housekeeping-tabs {
|
|
justify-content: flex-start;
|
|
}
|
|
|
|
.housekeeping-metrics,
|
|
.housekeeping-metrics--compact,
|
|
.housekeeping-form-grid,
|
|
.housekeeping-form-grid--wide,
|
|
.housekeeping-profile-editor {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.housekeeping-avatar--lg {
|
|
width: 84px;
|
|
height: 84px;
|
|
}
|
|
|
|
.housekeeping-worker-strip {
|
|
grid-template-columns: 48px 1fr;
|
|
}
|
|
|
|
.housekeeping-worker-strip .housekeeping-check-small {
|
|
grid-column: 1 / -1;
|
|
justify-content: center;
|
|
}
|
|
|
|
.housekeeping-section-heading {
|
|
align-items: stretch;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.housekeeping-staff-log-row {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.housekeeping-staff-log-row__actions {
|
|
justify-content: flex-end;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 420px) {
|
|
.housekeeping-check-small span {
|
|
display: none;
|
|
}
|
|
}
|