Keep view mode across tabs and speed up recommendation pipeline
This commit is contained in:
+135
-1
@@ -20,6 +20,9 @@
|
||||
--page-gutter: clamp(14px, 1.8vw, 24px);
|
||||
--panel-pad: clamp(16px, 1.4vw, 20px);
|
||||
--page-frame-width: min(1520px, calc(100vw - (var(--page-gutter) * 2)));
|
||||
--page-frame-width-dual: min(2560px, calc(100vw - (var(--page-gutter) * 2)));
|
||||
--page-frame-width-single: min(1520px, calc(100vw - (var(--page-gutter) * 2)));
|
||||
--status-widget-height: 34px;
|
||||
}
|
||||
|
||||
* {
|
||||
@@ -48,11 +51,28 @@
|
||||
padding: var(--page-gutter);
|
||||
}
|
||||
|
||||
body[data-view-mode="single"] {
|
||||
--page-frame-width: var(--page-frame-width-single);
|
||||
}
|
||||
|
||||
body[data-view-mode="dual"] {
|
||||
--page-frame-width: var(--page-frame-width-dual);
|
||||
--page-gutter: clamp(4px, 0.45vw, 10px);
|
||||
--panel-pad: clamp(12px, 1vw, 16px);
|
||||
}
|
||||
|
||||
.page {
|
||||
width: min(100%, var(--page-frame-width));
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
gap: var(--page-gutter);
|
||||
min-height: calc(100vh - (var(--page-gutter) * 2));
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
body[data-view-mode="dual"] .page {
|
||||
width: calc(100vw - (var(--page-gutter) * 2));
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.page > * {
|
||||
@@ -436,13 +456,81 @@
|
||||
border-radius: 999px;
|
||||
background: rgba(248, 250, 252, 0.92);
|
||||
box-shadow: none;
|
||||
padding: 6px 10px;
|
||||
min-height: var(--status-widget-height);
|
||||
padding: 0 10px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
|
||||
.view-mode-switch {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 80px;
|
||||
height: var(--status-widget-height);
|
||||
min-height: var(--status-widget-height);
|
||||
border-radius: 999px;
|
||||
border: 1px solid var(--line);
|
||||
background: #eef2f6;
|
||||
color: #1f2937;
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.01em;
|
||||
box-shadow: none;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.16s ease, border-color 0.16s ease;
|
||||
}
|
||||
|
||||
.view-mode-switch:hover {
|
||||
transform: none;
|
||||
background: #e7ecf2;
|
||||
}
|
||||
|
||||
.view-mode-switch .label {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 3px;
|
||||
width: 36px;
|
||||
transform: translateY(-50%);
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
transition: left 0.2s ease;
|
||||
}
|
||||
|
||||
.view-mode-switch::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 3px;
|
||||
width: 36px;
|
||||
height: calc(var(--status-widget-height) - 8px);
|
||||
border-radius: 999px;
|
||||
background: #111827;
|
||||
box-shadow: 0 6px 12px rgba(15, 23, 42, 0.18);
|
||||
transition: transform 0.2s ease;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.view-mode-switch[data-mode="dual"]::before {
|
||||
transform: translateX(38px);
|
||||
}
|
||||
|
||||
.view-mode-switch[data-mode="dual"] .label {
|
||||
left: 41px;
|
||||
}
|
||||
|
||||
.view-mode-switch[data-mode="single"]::before {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.sync-status-head {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
@@ -530,6 +618,9 @@
|
||||
<a href="/annual-summary" class="{% if request.url.path == '/annual-summary' %}active{% endif %}">연도별 수익/비용</a>
|
||||
<a href="/wehago-compare" class="{% if request.url.path == '/wehago-compare' %}active{% endif %}">전표비교</a>
|
||||
<div class="nav-spacer"></div>
|
||||
<button type="button" class="view-mode-switch" id="viewModeSwitch" data-mode="dual" aria-label="화면 구성 전환">
|
||||
<span class="label" id="viewModeSwitchLabel">듀얼</span>
|
||||
</button>
|
||||
<aside
|
||||
class="sync-status"
|
||||
id="syncStatusWidget"
|
||||
@@ -561,6 +652,49 @@
|
||||
</div>
|
||||
{% block script %}{% endblock %}
|
||||
<script>
|
||||
(() => {
|
||||
const body = document.body;
|
||||
const switchButton = document.getElementById("viewModeSwitch");
|
||||
const switchLabel = document.getElementById("viewModeSwitchLabel");
|
||||
if (!body || !switchButton || !switchLabel) return;
|
||||
|
||||
const MODE_KEY = "intranet-view-mode";
|
||||
const SOURCE_KEY = "intranet-view-mode-source";
|
||||
|
||||
const computeAutoMode = () => {
|
||||
const width = window.innerWidth || 0;
|
||||
const height = window.innerHeight || 1;
|
||||
const ratio = width / Math.max(height, 1);
|
||||
return (width >= 1450 || ratio >= 1.7) ? "dual" : "single";
|
||||
};
|
||||
|
||||
const applyMode = (mode) => {
|
||||
const normalized = mode === "single" ? "single" : "dual";
|
||||
body.dataset.viewMode = normalized;
|
||||
switchButton.dataset.mode = normalized;
|
||||
switchButton.setAttribute("aria-pressed", normalized === "single" ? "true" : "false");
|
||||
switchLabel.textContent = normalized === "single" ? "싱글" : "듀얼";
|
||||
};
|
||||
|
||||
const savedMode = window.localStorage.getItem(MODE_KEY);
|
||||
const savedSource = window.localStorage.getItem(SOURCE_KEY);
|
||||
if ((savedMode === "single" || savedMode === "dual") && savedSource === "manual") {
|
||||
applyMode(savedMode);
|
||||
} else {
|
||||
const autoMode = computeAutoMode();
|
||||
applyMode(autoMode);
|
||||
window.localStorage.setItem(MODE_KEY, autoMode);
|
||||
window.localStorage.setItem(SOURCE_KEY, "auto");
|
||||
}
|
||||
|
||||
switchButton.addEventListener("click", () => {
|
||||
const nextMode = body.dataset.viewMode === "single" ? "dual" : "single";
|
||||
applyMode(nextMode);
|
||||
window.localStorage.setItem(MODE_KEY, nextMode);
|
||||
window.localStorage.setItem(SOURCE_KEY, "manual");
|
||||
});
|
||||
})();
|
||||
|
||||
(() => {
|
||||
const widget = document.getElementById("syncStatusWidget");
|
||||
if (!widget) return;
|
||||
|
||||
Reference in New Issue
Block a user