Merge: 보고서 모달·일정 화면 다듬기 + 일정 컴포넌트 rem 통일
tweak/schedule-polish 머지 — 보고서 모달(전체탭 제거·상태버튼 축소·푸터 배경), 일정 화면 여백/마진 정리, 일정 하위 컴포넌트 px→rem 일괄 변환.
This commit is contained in:
@@ -90,16 +90,16 @@ function pick(v: ChecklistWorkStatus): void {
|
||||
.ss-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
height: 30px;
|
||||
min-width: 100px;
|
||||
padding: 0 9px 0 11px;
|
||||
gap: 6px;
|
||||
height: 26px;
|
||||
min-width: 86px;
|
||||
padding: 0 8px 0 9px;
|
||||
border: 1px solid var(--border-strong);
|
||||
border-radius: 8px;
|
||||
border-radius: 7px;
|
||||
background: var(--w);
|
||||
color: var(--c);
|
||||
font-family: inherit;
|
||||
font-size: 0.781rem;
|
||||
font-size: 0.719rem;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
@@ -108,8 +108,8 @@ function pick(v: ChecklistWorkStatus): void {
|
||||
border-color: var(--c);
|
||||
}
|
||||
.ss-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
background: var(--c);
|
||||
flex-shrink: 0;
|
||||
@@ -119,8 +119,8 @@ function pick(v: ChecklistWorkStatus): void {
|
||||
text-align: left;
|
||||
}
|
||||
.ss-chev {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
.ss-menu {
|
||||
position: fixed;
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
// 일정 참석자 아바타 — 사이트 공용 UserAvatar 를 size(px)로 감싸는 얇은 어댑터.
|
||||
// 렌더링(이미지/실루엣)은 UserAvatar 가 단일 책임지고, 여기선 크기/원형 래퍼만 담당.
|
||||
// (.sa 클래스는 상세 패널 아바타 스택 CSS 의 훅으로 유지)
|
||||
// size 는 px 로 받되 rem(÷16)으로 렌더 — 앱 전체 rem 스케일과 정합.
|
||||
import { computed } from 'vue'
|
||||
import UserAvatar from '@/components/UserAvatar.vue'
|
||||
|
||||
withDefaults(
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
name?: string
|
||||
avatarUrl?: string | null
|
||||
@@ -12,12 +14,13 @@ withDefaults(
|
||||
}>(),
|
||||
{ name: '', avatarUrl: null, size: 21 },
|
||||
)
|
||||
const dim = computed(() => `${props.size / 16}rem`)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span
|
||||
class="sa"
|
||||
:style="{ width: `${size}px`, height: `${size}px` }"
|
||||
:style="{ width: dim, height: dim }"
|
||||
>
|
||||
<UserAvatar
|
||||
:url="avatarUrl"
|
||||
|
||||
@@ -227,7 +227,7 @@ const extra = computed(() =>
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 360px;
|
||||
width: 22.5rem;
|
||||
z-index: 30;
|
||||
border-left: 1px solid var(--border);
|
||||
background: var(--panel);
|
||||
@@ -242,15 +242,15 @@ const extra = computed(() =>
|
||||
transform: translateX(0);
|
||||
}
|
||||
.type-chip {
|
||||
font-size: 11px;
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 600;
|
||||
padding: 2px 9px;
|
||||
border-radius: 6px;
|
||||
padding: 0.125rem 0.5625rem;
|
||||
border-radius: 0.375rem;
|
||||
white-space: nowrap;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.dt-head {
|
||||
padding: 20px 22px 18px;
|
||||
padding: 1.25rem 1.375rem 1.125rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -260,8 +260,8 @@ const extra = computed(() =>
|
||||
justify-content: space-between;
|
||||
}
|
||||
.dt-close {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
width: 1.875rem;
|
||||
height: 1.875rem;
|
||||
border-radius: var(--radius-sm);
|
||||
border: none;
|
||||
background: transparent;
|
||||
@@ -269,48 +269,48 @@ const extra = computed(() =>
|
||||
cursor: pointer;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
margin-right: -6px;
|
||||
margin-right: -0.375rem;
|
||||
}
|
||||
.dt-close:hover {
|
||||
background: #f1f2f4;
|
||||
color: var(--text);
|
||||
}
|
||||
.dt-close svg {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
width: 1.0625rem;
|
||||
height: 1.0625rem;
|
||||
}
|
||||
.dt-head h2 {
|
||||
font-size: 18px;
|
||||
font-size: 1.125rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.3px;
|
||||
letter-spacing: -0.0187rem;
|
||||
line-height: 1.4;
|
||||
margin: 13px 0 8px;
|
||||
margin: 0.8125rem 0 0.5rem;
|
||||
word-break: keep-all;
|
||||
}
|
||||
.dt-date {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
font-size: 13px;
|
||||
gap: 0.4375rem;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-2);
|
||||
}
|
||||
.dt-date svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
width: 0.9375rem;
|
||||
height: 0.9375rem;
|
||||
color: var(--text-3);
|
||||
}
|
||||
.dt-dur {
|
||||
font-size: 11px;
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent);
|
||||
background: var(--accent-weak);
|
||||
border-radius: 5px;
|
||||
padding: 1px 7px;
|
||||
border-radius: 0.3125rem;
|
||||
padding: 0.0625rem 0.4375rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.dt-body {
|
||||
padding: 18px 22px 24px;
|
||||
padding: 1.125rem 1.375rem 1.5rem;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
@@ -318,25 +318,25 @@ const extra = computed(() =>
|
||||
.dt-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
gap: 1rem;
|
||||
}
|
||||
.dt-item {
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
gap: 0.875rem;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.dt-k {
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-3);
|
||||
width: 52px;
|
||||
width: 3.25rem;
|
||||
flex-shrink: 0;
|
||||
padding-top: 2px;
|
||||
padding-top: 0.125rem;
|
||||
}
|
||||
.dt-v {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 13.5px;
|
||||
font-size: 0.8438rem;
|
||||
font-weight: 500;
|
||||
color: var(--text);
|
||||
word-break: keep-all;
|
||||
@@ -349,18 +349,18 @@ const extra = computed(() =>
|
||||
}
|
||||
.att-stack {
|
||||
position: relative;
|
||||
margin: -3px 0;
|
||||
margin: -0.1875rem 0;
|
||||
}
|
||||
.att-trigger {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 9px;
|
||||
gap: 0.5625rem;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
padding: 5px 8px 5px 5px;
|
||||
margin: -5px -8px -5px -5px;
|
||||
border-radius: 9px;
|
||||
padding: 0.3125rem 0.5rem 0.3125rem 0.3125rem;
|
||||
margin: -0.3125rem -0.5rem -0.3125rem -0.3125rem;
|
||||
border-radius: 0.5625rem;
|
||||
}
|
||||
.att-trigger:hover,
|
||||
.att-trigger.open {
|
||||
@@ -372,19 +372,19 @@ const extra = computed(() =>
|
||||
}
|
||||
.avstack :deep(.sa),
|
||||
.avstack .av-more {
|
||||
margin-left: -9px;
|
||||
margin-left: -0.5625rem;
|
||||
box-shadow: 0 0 0 2px var(--panel);
|
||||
}
|
||||
.avstack :deep(.sa):first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
.av-more {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
width: 1.875rem;
|
||||
height: 1.875rem;
|
||||
border-radius: 50%;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
background: #eceef1;
|
||||
color: var(--text-2);
|
||||
@@ -396,36 +396,36 @@ const extra = computed(() =>
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
.att-chev svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
width: 0.9375rem;
|
||||
height: 0.9375rem;
|
||||
}
|
||||
.att-trigger.open .att-chev {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
.att-panel {
|
||||
position: absolute;
|
||||
top: calc(100% + 6px);
|
||||
top: calc(100% + 0.375rem);
|
||||
left: 0;
|
||||
min-width: 200px;
|
||||
max-width: 260px;
|
||||
max-height: 240px;
|
||||
min-width: 12.5rem;
|
||||
max-width: 16.25rem;
|
||||
max-height: 15rem;
|
||||
overflow-y: auto;
|
||||
z-index: 20;
|
||||
background: var(--panel);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
border-radius: 0.625rem;
|
||||
box-shadow: var(--shadow-md);
|
||||
padding: 5px;
|
||||
padding: 0.3125rem;
|
||||
}
|
||||
.att-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 9px;
|
||||
font-size: 13px;
|
||||
gap: 0.5625rem;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 500;
|
||||
color: var(--text);
|
||||
padding: 6px 8px;
|
||||
border-radius: 6px;
|
||||
padding: 0.375rem 0.5rem;
|
||||
border-radius: 0.375rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.att-row:hover {
|
||||
@@ -433,27 +433,27 @@ const extra = computed(() =>
|
||||
}
|
||||
.dt-foot {
|
||||
flex-shrink: 0;
|
||||
padding: 14px 22px;
|
||||
padding: 0.875rem 1.375rem;
|
||||
border-top: 1px solid var(--border);
|
||||
background: var(--panel);
|
||||
}
|
||||
.dt-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.dt-actions .btn {
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
height: 36px;
|
||||
height: 2.25rem;
|
||||
}
|
||||
.dt-actions .btn.icon-only {
|
||||
flex: 0 0 auto;
|
||||
padding: 0;
|
||||
width: 36px;
|
||||
width: 2.25rem;
|
||||
}
|
||||
.btn {
|
||||
border-radius: var(--radius);
|
||||
font-size: 13.5px;
|
||||
font-size: 0.8438rem;
|
||||
font-weight: 600;
|
||||
border: 1px solid var(--border-strong);
|
||||
background: var(--panel);
|
||||
@@ -461,7 +461,7 @@ const extra = computed(() =>
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
gap: 0.375rem;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -470,8 +470,8 @@ const extra = computed(() =>
|
||||
color: var(--text);
|
||||
}
|
||||
.btn svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
width: 0.9375rem;
|
||||
height: 0.9375rem;
|
||||
}
|
||||
.btn.danger {
|
||||
background: #fff;
|
||||
|
||||
@@ -418,20 +418,20 @@ function submit(): void {
|
||||
height: 0.9375rem;
|
||||
}
|
||||
.ms-all {
|
||||
/* 참석자 아바타(ScheduleAvatar :size="20" = 20px)와 동일 크기 */
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
/* 참석자 아바타(ScheduleAvatar :size="20" = 1.25rem)와 동일 크기 */
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
border-radius: 50%;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
font-size: 9px;
|
||||
font-size: 0.5625rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
background: #9298a3;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.ms-div {
|
||||
height: 1px;
|
||||
height: 0.0625rem;
|
||||
background: var(--border);
|
||||
margin: 0.25rem 0.125rem;
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ function onBodyScroll(): void {
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
border-radius: 0.75rem;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
.tl-head-scroll {
|
||||
@@ -254,27 +254,27 @@ function onBodyScroll(): void {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 7px;
|
||||
padding: 9px 8px;
|
||||
gap: 0.4375rem;
|
||||
padding: 0.5625rem 0.5rem;
|
||||
text-align: center;
|
||||
border-left: 1px solid var(--border);
|
||||
}
|
||||
.tl-dayhead .sdow {
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-3);
|
||||
letter-spacing: 0.2px;
|
||||
letter-spacing: 0.0125rem;
|
||||
}
|
||||
.tl-dayhead .sd {
|
||||
display: inline-grid;
|
||||
place-items: center;
|
||||
min-width: 26px;
|
||||
height: 26px;
|
||||
padding: 0 5px;
|
||||
font-size: 15px;
|
||||
min-width: 1.625rem;
|
||||
height: 1.625rem;
|
||||
padding: 0 0.3125rem;
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.3px;
|
||||
border-radius: 13px;
|
||||
letter-spacing: -0.0187rem;
|
||||
border-radius: 0.8125rem;
|
||||
}
|
||||
.tl-dayhead.is-today .sdow {
|
||||
color: var(--accent);
|
||||
@@ -301,9 +301,9 @@ function onBodyScroll(): void {
|
||||
.tl-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 9px;
|
||||
padding: 0 8px 0 14px;
|
||||
font-size: 13.5px;
|
||||
gap: 0.5625rem;
|
||||
padding: 0 0.5rem 0 0.875rem;
|
||||
font-size: 0.8438rem;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
position: sticky;
|
||||
@@ -314,9 +314,9 @@ function onBodyScroll(): void {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tl-label .dot {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
border-radius: 3px;
|
||||
width: 0.6875rem;
|
||||
height: 0.6875rem;
|
||||
border-radius: 0.1875rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.tl-label .ll-name {
|
||||
@@ -333,12 +333,12 @@ function onBodyScroll(): void {
|
||||
left: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
padding: 11px 14px;
|
||||
gap: 0.4375rem;
|
||||
padding: 0.6875rem 0.875rem;
|
||||
background: var(--panel);
|
||||
border: none;
|
||||
font-family: inherit;
|
||||
font-size: 13px;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-3);
|
||||
cursor: pointer;
|
||||
@@ -347,8 +347,8 @@ function onBodyScroll(): void {
|
||||
color: var(--accent);
|
||||
}
|
||||
.tl-addcat svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
width: 0.9375rem;
|
||||
height: 0.9375rem;
|
||||
}
|
||||
|
||||
.tl-track {
|
||||
@@ -372,19 +372,19 @@ function onBodyScroll(): void {
|
||||
.tl-bars {
|
||||
position: relative;
|
||||
display: grid;
|
||||
row-gap: 7px;
|
||||
row-gap: 0.4375rem;
|
||||
column-gap: 0;
|
||||
padding: 9px 0;
|
||||
padding: 0.5625rem 0;
|
||||
}
|
||||
.tl-bar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 1px;
|
||||
margin: 0 6px;
|
||||
padding: 0 11px;
|
||||
gap: 0.0625rem;
|
||||
margin: 0 0.375rem;
|
||||
padding: 0 0.6875rem;
|
||||
height: 100%;
|
||||
border-radius: 7px;
|
||||
border-radius: 0.4375rem;
|
||||
background: var(--bar-weak);
|
||||
border-left: 3px solid var(--bar-color);
|
||||
cursor: pointer;
|
||||
@@ -395,10 +395,10 @@ function onBodyScroll(): void {
|
||||
}
|
||||
.tl-bar:hover {
|
||||
box-shadow: 0 3px 10px rgba(20, 24, 33, 0.13);
|
||||
transform: translateY(-1px);
|
||||
transform: translateY(-0.0625rem);
|
||||
}
|
||||
.tl-bar .bt {
|
||||
font-size: 12.5px;
|
||||
font-size: 0.7813rem;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
line-height: 1.3;
|
||||
@@ -413,10 +413,10 @@ function onBodyScroll(): void {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
padding: 40px;
|
||||
gap: 0.625rem;
|
||||
padding: 2.5rem;
|
||||
color: var(--text-3);
|
||||
font-size: 13.5px;
|
||||
font-size: 0.8438rem;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -207,39 +207,39 @@ const allOn = computed(
|
||||
}
|
||||
.filter-menu {
|
||||
position: absolute;
|
||||
top: calc(100% + 7px);
|
||||
top: calc(100% + 0.4375rem);
|
||||
right: 0;
|
||||
z-index: 60;
|
||||
width: 264px;
|
||||
width: 16.5rem;
|
||||
background: var(--panel);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
border-radius: 0.625rem;
|
||||
box-shadow: var(--shadow-pop);
|
||||
padding: 6px;
|
||||
padding: 0.375rem;
|
||||
}
|
||||
.fm-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 7px 8px 9px;
|
||||
padding: 0.4375rem 0.5rem 0.5625rem;
|
||||
}
|
||||
.fm-head > span {
|
||||
font-size: 11px;
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 700;
|
||||
color: var(--text-3);
|
||||
letter-spacing: 0.3px;
|
||||
letter-spacing: 0.0187rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.fm-all {
|
||||
border: none;
|
||||
background: none;
|
||||
font-family: inherit;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
color: var(--accent);
|
||||
cursor: pointer;
|
||||
padding: 2px 5px;
|
||||
border-radius: 4px;
|
||||
padding: 0.125rem 0.3125rem;
|
||||
border-radius: 0.25rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.fm-all:hover {
|
||||
@@ -248,13 +248,13 @@ const allOn = computed(
|
||||
.fm-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 320px;
|
||||
max-height: 20rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.fm-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 6px;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
.fm-item:hover {
|
||||
background: #f4f5f7;
|
||||
@@ -264,20 +264,20 @@ const allOn = computed(
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 9px;
|
||||
gap: 0.5625rem;
|
||||
border: none;
|
||||
background: none;
|
||||
font-family: inherit;
|
||||
font-size: 13px;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
padding: 8px;
|
||||
padding: 0.5rem;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
}
|
||||
.fm-tog .dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 3px;
|
||||
width: 0.625rem;
|
||||
height: 0.625rem;
|
||||
border-radius: 0.1875rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.fm-tog .fm-label {
|
||||
@@ -289,21 +289,21 @@ const allOn = computed(
|
||||
white-space: nowrap;
|
||||
}
|
||||
.fm-tog .fm-ct {
|
||||
font-size: 11px;
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 700;
|
||||
color: var(--text-3);
|
||||
}
|
||||
.fm-tog .fm-check {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
flex-shrink: 0;
|
||||
color: var(--accent);
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
.fm-tog .fm-check svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
width: 0.9375rem;
|
||||
height: 0.9375rem;
|
||||
}
|
||||
.fm-item:not(.on) .fm-label {
|
||||
color: var(--text-3);
|
||||
@@ -313,19 +313,19 @@ const allOn = computed(
|
||||
}
|
||||
.fm-acts {
|
||||
display: none;
|
||||
gap: 1px;
|
||||
padding-right: 5px;
|
||||
gap: 0.0625rem;
|
||||
padding-right: 0.3125rem;
|
||||
}
|
||||
.fm-item:hover .fm-acts {
|
||||
display: flex;
|
||||
}
|
||||
.fm-act {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
width: 1.5625rem;
|
||||
height: 1.5625rem;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--text-3);
|
||||
border-radius: 5px;
|
||||
border-radius: 0.3125rem;
|
||||
cursor: pointer;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
@@ -335,30 +335,30 @@ const allOn = computed(
|
||||
color: var(--text);
|
||||
}
|
||||
.fm-act svg {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
width: 0.8125rem;
|
||||
height: 0.8125rem;
|
||||
}
|
||||
.fm-add {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
gap: 0.4375rem;
|
||||
width: 100%;
|
||||
border: none;
|
||||
border-top: 1px solid var(--border);
|
||||
background: none;
|
||||
font-family: inherit;
|
||||
font-size: 13px;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
color: var(--accent);
|
||||
padding: 10px 8px 6px;
|
||||
margin-top: 4px;
|
||||
padding: 0.625rem 0.5rem 0.375rem;
|
||||
margin-top: 0.25rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
.fm-add:hover {
|
||||
color: var(--accent-hover);
|
||||
}
|
||||
.fm-add svg {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
width: 0.9375rem;
|
||||
height: 0.9375rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -222,7 +222,10 @@ async function onDeleteCategory(id: string): Promise<void> {
|
||||
align-items: center;
|
||||
/* 프로젝트 목록 등 전역 .toolbar 와 동일한 컨트롤 간격 */
|
||||
gap: 0.625rem;
|
||||
padding: 11px 24px;
|
||||
/* 가로 여백은 .page(0 1.5rem)·콘텐츠 영역과 동일하게 1.5rem */
|
||||
padding: 0.6875rem 1.5rem;
|
||||
/* 전역 .toolbar 의 margin-bottom(0.875rem) 상속 차단 — 고정 바라 여분 마진 불필요 */
|
||||
margin-bottom: 0;
|
||||
flex-shrink: 0;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: var(--panel);
|
||||
@@ -230,14 +233,14 @@ async function onDeleteCategory(id: string): Promise<void> {
|
||||
.datenav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.datenav .range {
|
||||
font-size: 15.5px;
|
||||
font-size: 0.969rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.3px;
|
||||
letter-spacing: -0.01875rem;
|
||||
white-space: nowrap;
|
||||
margin: 0 6px;
|
||||
margin: 0 0.375rem;
|
||||
}
|
||||
.navgroup {
|
||||
display: flex;
|
||||
@@ -250,8 +253,8 @@ async function onDeleteCategory(id: string): Promise<void> {
|
||||
margin-left: -1px;
|
||||
}
|
||||
.navbtn {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
border: 1px solid var(--border-strong);
|
||||
background: #fff;
|
||||
color: var(--text-2);
|
||||
@@ -265,8 +268,8 @@ async function onDeleteCategory(id: string): Promise<void> {
|
||||
z-index: 1;
|
||||
}
|
||||
.navbtn svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
.spacer {
|
||||
flex: 1;
|
||||
@@ -285,7 +288,8 @@ async function onDeleteCategory(id: string): Promise<void> {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
padding: 18px 24px 28px;
|
||||
/* 콘텐츠 영역 상하좌우 여백 통일(1.5rem) — 툴바 가로 여백·.page 와 일치 */
|
||||
padding: 1.5rem;
|
||||
}
|
||||
.detail-backdrop {
|
||||
position: absolute;
|
||||
|
||||
@@ -314,7 +314,13 @@ const CAT_COLOR: Record<ChecklistCategory, string> = {
|
||||
보안: '#dc2626',
|
||||
부가: '#b7791f',
|
||||
}
|
||||
type CatTab = ChecklistCategory | 'all'
|
||||
// 보고서 모달 탭 — 카테고리(전체 탭 없음). 기본 탭은 항목이 있는 첫 분류.
|
||||
type CatTab = ChecklistCategory
|
||||
function firstCat(items: { category: ChecklistCategory }[]): ChecklistCategory {
|
||||
return (
|
||||
CHECKLIST_CATEGORIES.find((c) => items.some((i) => i.category === c)) ?? '필수'
|
||||
)
|
||||
}
|
||||
|
||||
// KST(UTC+9) 기준 'yyyy-MM-dd' — '당일' 판정
|
||||
function kstDate(iso: string | Date): string {
|
||||
@@ -349,12 +355,11 @@ const reportItems = ref<
|
||||
>([])
|
||||
const reportNote = ref('')
|
||||
const reportSubmitting = ref(false)
|
||||
const writeTab = ref<CatTab>('all')
|
||||
const writeTab = ref<CatTab>('필수')
|
||||
|
||||
function openReportForm(cp: TaskCheckpointView) {
|
||||
if (!task.value) return
|
||||
reportingCpId.value = cp.id
|
||||
writeTab.value = 'all'
|
||||
// 현재(마지막 보고) 상태로 프리필
|
||||
reportItems.value = task.value.checklist
|
||||
.filter((c) => c.id)
|
||||
@@ -364,16 +369,11 @@ function openReportForm(cp: TaskCheckpointView) {
|
||||
category: c.category,
|
||||
workStatus: c.workStatus ?? 'todo',
|
||||
}))
|
||||
writeTab.value = firstCat(reportItems.value)
|
||||
reportNote.value = ''
|
||||
}
|
||||
// 작성 모달 — 탭별 그룹/개수/요약
|
||||
// 작성 모달 — 선택 분류의 그룹/개수/요약
|
||||
const writeGroups = computed(() => {
|
||||
if (writeTab.value === 'all') {
|
||||
return CHECKLIST_CATEGORIES.map((c) => ({
|
||||
cat: c,
|
||||
items: reportItems.value.filter((i) => i.category === c),
|
||||
})).filter((g) => g.items.length)
|
||||
}
|
||||
const c = writeTab.value
|
||||
return [{ cat: c, items: reportItems.value.filter((i) => i.category === c) }]
|
||||
})
|
||||
@@ -387,11 +387,7 @@ const writeSummary = computed(() =>
|
||||
})),
|
||||
)
|
||||
// 현재 탭에서 보이는 항목 수(0이면 빈 안내 표시)
|
||||
const writeVisible = computed(() =>
|
||||
writeTab.value === 'all'
|
||||
? reportItems.value.length
|
||||
: writeCatCount(writeTab.value),
|
||||
)
|
||||
const writeVisible = computed(() => writeCatCount(writeTab.value))
|
||||
function cancelReportForm() {
|
||||
reportingCpId.value = null
|
||||
reportItems.value = []
|
||||
@@ -418,33 +414,24 @@ async function submitReport() {
|
||||
|
||||
// --- 보고 기록 열람(모달) — 전체/카테고리 탭 ---
|
||||
const openedReport = ref<CheckpointReportView | null>(null)
|
||||
const viewTab = ref<CatTab>('all')
|
||||
const viewTab = ref<CatTab>('필수')
|
||||
// 보고 완료 체크포인트 클릭 → 해당 체크포인트의 최신 보고를 모달로 연다
|
||||
function openReportModal(cp: TaskCheckpointView) {
|
||||
const r = task.value?.checkpointReports.find((x) => x.checkpointId === cp.id)
|
||||
if (!r) return
|
||||
openedReport.value = r
|
||||
viewTab.value = 'all'
|
||||
viewTab.value = firstCat(r.items)
|
||||
}
|
||||
const viewItems = computed(() => openedReport.value?.items ?? [])
|
||||
const viewGroups = computed(() => {
|
||||
const items = viewItems.value
|
||||
if (viewTab.value === 'all') {
|
||||
return CHECKLIST_CATEGORIES.map((c) => ({
|
||||
cat: c,
|
||||
items: items.filter((i) => i.category === c),
|
||||
})).filter((g) => g.items.length)
|
||||
}
|
||||
const c = viewTab.value
|
||||
return [{ cat: c, items: items.filter((i) => i.category === c) }]
|
||||
return [{ cat: c, items: viewItems.value.filter((i) => i.category === c) }]
|
||||
})
|
||||
function viewCatCount(cat: ChecklistCategory): number {
|
||||
return viewItems.value.filter((i) => i.category === cat).length
|
||||
}
|
||||
// 현재 탭에서 보이는 항목 수(0이면 빈 안내 표시)
|
||||
const viewVisible = computed(() =>
|
||||
viewTab.value === 'all' ? viewItems.value.length : viewCatCount(viewTab.value),
|
||||
)
|
||||
const viewVisible = computed(() => viewCatCount(viewTab.value))
|
||||
const reporterInitial = computed(() => openedReport.value?.reporterName?.[0] ?? '?')
|
||||
// 담당자 액션 카드 테마(시안): changes→빨강 / review→앰버 / done→초록 / 그 외→accent
|
||||
const assigneeCardClass = computed(() => {
|
||||
@@ -1674,14 +1661,6 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
|
||||
class="pr-tabs"
|
||||
role="tablist"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="pr-tab"
|
||||
:class="{ on: viewTab === 'all' }"
|
||||
@click="viewTab = 'all'"
|
||||
>
|
||||
전체<span class="pr-tct">{{ viewItems.length }}</span>
|
||||
</button>
|
||||
<button
|
||||
v-for="c in CHECKLIST_CATEGORIES"
|
||||
:key="c"
|
||||
@@ -1702,15 +1681,6 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
|
||||
v-for="g in viewGroups"
|
||||
:key="g.cat"
|
||||
>
|
||||
<div
|
||||
v-if="viewTab === 'all'"
|
||||
class="pr-ghead"
|
||||
>
|
||||
<span
|
||||
class="pr-gdot"
|
||||
:style="{ background: CAT_COLOR[g.cat] }"
|
||||
/>{{ g.cat }}<span class="pr-gct">· {{ g.items.length }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-for="(it, i) in g.items"
|
||||
:key="g.cat + '-' + i"
|
||||
@@ -1733,7 +1703,7 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
|
||||
v-if="viewVisible === 0"
|
||||
class="pr-empty"
|
||||
>
|
||||
{{ viewTab === 'all' ? '보고된 항목이 없습니다.' : `'${viewTab}' 분류에 항목이 없습니다.` }}
|
||||
'{{ viewTab }}' 분류에 항목이 없습니다.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1810,14 +1780,6 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
|
||||
class="pr-tabs"
|
||||
role="tablist"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="pr-tab"
|
||||
:class="{ on: writeTab === 'all' }"
|
||||
@click="writeTab = 'all'"
|
||||
>
|
||||
전체<span class="pr-tct">{{ reportItems.length }}</span>
|
||||
</button>
|
||||
<button
|
||||
v-for="c in CHECKLIST_CATEGORIES"
|
||||
:key="c"
|
||||
@@ -1838,15 +1800,6 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
|
||||
v-for="g in writeGroups"
|
||||
:key="g.cat"
|
||||
>
|
||||
<div
|
||||
v-if="writeTab === 'all'"
|
||||
class="pr-ghead"
|
||||
>
|
||||
<span
|
||||
class="pr-gdot"
|
||||
:style="{ background: CAT_COLOR[g.cat] }"
|
||||
/>{{ g.cat }}<span class="pr-gct">· {{ g.items.length }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-for="it in g.items"
|
||||
:key="it.id"
|
||||
@@ -1861,7 +1814,7 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
|
||||
v-if="writeVisible === 0"
|
||||
class="pr-empty"
|
||||
>
|
||||
{{ writeTab === 'all' ? '보고할 할 일이 없습니다. 메모만 전송됩니다.' : `'${writeTab}' 분류에 할 일이 없습니다.` }}
|
||||
'{{ writeTab }}' 분류에 할 일이 없습니다.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3807,24 +3760,6 @@ a.file-info {
|
||||
padding: 0 1.5rem 0.5rem;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
.pr-ghead {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 1rem 0.125rem 0.4375rem;
|
||||
font-size: 0.719rem;
|
||||
font-weight: 700;
|
||||
color: var(--text-3);
|
||||
}
|
||||
.pr-ghead .pr-gdot {
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.pr-ghead .pr-gct {
|
||||
color: var(--text-3);
|
||||
font-weight: 600;
|
||||
}
|
||||
.pr-task,
|
||||
.pr-titem {
|
||||
display: flex;
|
||||
@@ -3947,6 +3882,8 @@ a.file-info {
|
||||
gap: 0.75rem;
|
||||
padding: 0.875rem 1.5rem;
|
||||
border-top: 1px solid var(--border);
|
||||
/* 다른 모달 푸터(BaseModal .bm-foot)와 동일한 배경 */
|
||||
background: #fafbfc;
|
||||
}
|
||||
.pr-foot .pr-sp {
|
||||
flex: 1;
|
||||
|
||||
Reference in New Issue
Block a user