feat: Flask 애플리케이션 모듈화 및 웹 대시보드 구현
- Flask Blueprint 아키텍처로 전환 (dashboard, upload, backup, status) - app.py 681줄 95줄로 축소 (86% 감소) - HTML 템플릿 모듈화 (base.html + 기능별 templates) - CSS/JS 파일 분리 (common + 기능별 파일) - 대시보드 기능 추가 (통계, 주간 예보, 방문객 추이) - 파일 업로드 웹 인터페이스 구현 - 백업/복구 관리 UI 구현 - Docker 배포 환경 개선 - .gitignore 업데이트 (uploads, backups, cache 등)
This commit is contained in:
108
app/templates/dashboard.html
Normal file
108
app/templates/dashboard.html
Normal file
@ -0,0 +1,108 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}대시보드 - First Garden POS{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link href="{{ url_for('static', filename='css/dashboard.css') }}" rel="stylesheet">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="tab-pane fade show active" id="dashboard-panel" role="tabpanel">
|
||||
<!-- 통계 카드 -->
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="stat-card okpos-product">
|
||||
<h3>OKPOS 상품별</h3>
|
||||
<div class="stat-value" id="okpos-product-count">-</div>
|
||||
<div class="stat-label">총 데이터</div>
|
||||
<div class="stat-label" id="okpos-product-days">-</div>
|
||||
<div class="stat-date" id="okpos-product-date">최종: -</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="stat-card okpos-receipt">
|
||||
<h3>OKPOS 영수증</h3>
|
||||
<div class="stat-value" id="okpos-receipt-count">-</div>
|
||||
<div class="stat-label">총 데이터</div>
|
||||
<div class="stat-label" id="okpos-receipt-days">-</div>
|
||||
<div class="stat-date" id="okpos-receipt-date">최종: -</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="stat-card upsolution">
|
||||
<h3>UPSolution</h3>
|
||||
<div class="stat-value" id="upsolution-count">-</div>
|
||||
<div class="stat-label">총 데이터</div>
|
||||
<div class="stat-label" id="upsolution-days">-</div>
|
||||
<div class="stat-date" id="upsolution-date">최종: -</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="stat-card weather">
|
||||
<h3>날씨 데이터</h3>
|
||||
<div class="stat-value" id="weather-count">-</div>
|
||||
<div class="stat-label">총 데이터</div>
|
||||
<div class="stat-label" id="weather-days">-</div>
|
||||
<div class="stat-date" id="weather-date">최종: -</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 주간 예보 테이블 -->
|
||||
<div style="margin-top: 30px;">
|
||||
<h5 style="margin-bottom: 20px; font-weight: 600; color: #333;">
|
||||
<i class="bi bi-calendar-event"></i> 이번주 예상 날씨 & 방문객
|
||||
</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>날짜</th>
|
||||
<th>최저기온</th>
|
||||
<th>최고기온</th>
|
||||
<th>강수량</th>
|
||||
<th>습도</th>
|
||||
<th>예상 방문객</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="weekly-forecast-table">
|
||||
<tr>
|
||||
<td colspan="6" class="text-center text-muted">데이터 로딩 중...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 방문객 추이 그래프 -->
|
||||
<div style="margin-top: 30px;">
|
||||
<h5 style="margin-bottom: 20px; font-weight: 600; color: #333;">
|
||||
<i class="bi bi-graph-up"></i> 방문객 추이
|
||||
</h5>
|
||||
|
||||
<!-- 날짜 범위 선택 -->
|
||||
<div class="date-range-picker">
|
||||
<input type="date" id="trend-start-date" class="form-control" style="max-width: 150px;">
|
||||
<span style="display: flex; align-items: center;">~</span>
|
||||
<input type="date" id="trend-end-date" class="form-control" style="max-width: 150px;">
|
||||
<button class="btn btn-primary btn-sm" onclick="loadVisitorTrend()">조회</button>
|
||||
<button class="btn btn-outline-primary btn-sm" onclick="resetTrendDate()">최근 1개월</button>
|
||||
</div>
|
||||
|
||||
<!-- 그래프 -->
|
||||
<div class="chart-container">
|
||||
<canvas id="visitor-trend-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script src="{{ url_for('static', filename='js/dashboard.js') }}"></script>
|
||||
<script>
|
||||
// 대시보드 초기화
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
initializeDashboard();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user