UXを向上

This commit is contained in:
2026-01-08 23:31:49 +09:00
parent f0712bddfe
commit c87e71d1ac
5 changed files with 117 additions and 54 deletions

View File

@@ -151,8 +151,8 @@ REST API認証用のAPIキーを管理するモデル。
| 機能 | 説明 |
|------|------|
| ダッシュボード | 課題の統計情報、本日期限の課題、期限切れ課題、今週期限の課題を表示 |
| 課題一覧 | フィルタ付き(未完了/完了済み/期限切れ)で課題を一覧表示 |
| ダッシュボード | 課題の統計情報、本日期限の課題、期限切れ課題、今週期限の課題を表示。各統計カードをクリックすると対応するフィルタで課題一覧に遷移 |
| 課題一覧 | フィルタ付き(未完了/今日が期限/今週が期限/完了済み/期限切れ)で課題を一覧表示 |
| 課題登録 | タイトル、説明、教科、重要度、提出期限、通知設定を入力して新規登録 |
| 課題編集 | 既存の課題情報を編集 |
| 課題削除 | 課題を論理削除 |

View File

@@ -148,11 +148,19 @@ func (r *AssignmentRepository) Search(userID uint, queryStr, priority, filter st
}
now := time.Now()
startOfDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
endOfDay := startOfDay.AddDate(0, 0, 1)
weekLater := startOfDay.AddDate(0, 0, 7)
switch filter {
case "completed":
dbQuery = dbQuery.Where("is_completed = ?", true)
case "overdue":
dbQuery = dbQuery.Where("is_completed = ? AND due_date < ?", false, now)
case "due_today":
dbQuery = dbQuery.Where("is_completed = ? AND due_date >= ? AND due_date < ?", false, startOfDay, endOfDay)
case "due_this_week":
dbQuery = dbQuery.Where("is_completed = ? AND due_date >= ? AND due_date < ?", false, startOfDay, weekLater)
default: // pending
dbQuery = dbQuery.Where("is_completed = ?", false)
}
@@ -195,12 +203,12 @@ type StatisticsFilter struct {
}
type AssignmentStatistics struct {
Total int64
Completed int64
Pending int64
Overdue int64
CompletedOnTime int64
OnTimeCompletionRate float64
Total int64
Completed int64
Pending int64
Overdue int64
CompletedOnTime int64
OnTimeCompletionRate float64
}
type SubjectStatistics struct {
@@ -338,4 +346,3 @@ func (r *AssignmentRepository) GetSubjectsByUserIDWithArchived(userID uint, incl
err := query.Distinct("subject").Pluck("subject", &subjects).Error
return subjects, err
}

View File

@@ -18,19 +18,43 @@
<!-- Tabs -->
<ul class="nav nav-tabs border-0 mb-2" id="assignmentTabs">
<li class="nav-item">
<a class="nav-link py-2 rounded-0 border-0 {{if eq .filter " pending"}}fw-bold border-bottom border-dark
border-3{{else}}text-muted{{end}}" href="/assignments?filter=pending&q={{.query}}&priority={{.priority}}"
style="{{if eq .filter " pending"}}color: black !important;{{end}}">未完了</a>
<a class="nav-link py-2 rounded-0 {{if eq .filter "pending"}}fw-bold border-bottom border-dark border-3
text-dark{{else}}border-0 text-muted{{end}}"
href="/assignments?filter=pending&q={{.query}}&priority={{.priority}}">
未完了
</a>
</li>
<li class="nav-item">
<a class="nav-link py-2 rounded-0 border-0 {{if eq .filter " completed"}}fw-bold border-bottom border-dark
border-3{{else}}text-muted{{end}}" href="/assignments?filter=completed&q={{.query}}&priority={{.priority}}"
style="{{if eq .filter " completed"}}color: black !important;{{end}}">完了済み</a>
<a class="nav-link py-2 rounded-0 {{if eq .filter "due_today"}}fw-bold border-bottom border-dark border-3
text-dark{{else}}border-0 text-muted{{end}}"
href="/assignments?filter=due_today&q={{.query}}&priority={{.priority}}">
今日が期限
</a>
</li>
<li class="nav-item">
<a class="nav-link py-2 rounded-0 border-0 {{if eq .filter " overdue"}}fw-bold border-bottom border-dark
border-3{{else}}text-muted{{end}}" href="/assignments?filter=overdue&q={{.query}}&priority={{.priority}}"
style="{{if eq .filter " overdue"}}color: black !important;{{end}}">期限切れ</a>
<a class="nav-link py-2 rounded-0 {{if eq .filter "due_this_week"}}fw-bold border-bottom border-dark border-3
text-dark{{else}}border-0 text-muted{{end}}"
href="/assignments?filter=due_this_week&q={{.query}}&priority={{.priority}}">
今週が期限
</a>
</li>
<li class="nav-item">
<a class="nav-link py-2 rounded-0 {{if eq .filter "completed"}}fw-bold border-bottom border-dark border-3
text-dark{{else}}border-0 text-muted{{end}}"
href="/assignments?filter=completed&q={{.query}}&priority={{.priority}}">
完了済み
</a>
</li>
<li class="nav-item">
<a class="nav-link py-2 rounded-0 {{if eq .filter "overdue"}}fw-bold border-bottom border-dark border-3
text-dark{{else}}border-0 text-muted{{end}}"
href="/assignments?filter=overdue&q={{.query}}&priority={{.priority}}">
期限切れ
</a>
</li>
</ul>
<hr class="mt-0 mb-3 text-muted" style="opacity: 0.1;">

View File

@@ -30,6 +30,20 @@
.pagination-info {
font-size: 0.875rem;
}
.stats-table {
min-width: 700px;
}
.stats-table th,
.stats-table td {
white-space: nowrap;
}
.stats-table th:first-child,
.stats-table td:first-child {
min-width: 120px;
}
</style>
{{end}}
@@ -174,7 +188,7 @@
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<table class="table table-hover mb-0 stats-table">
<thead class="table-light">
<tr>
<th>科目</th>
@@ -206,7 +220,7 @@
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<table class="table table-hover mb-0 stats-table">
<thead class="table-light">
<tr>
<th>科目</th>

View File

@@ -65,6 +65,16 @@
font-size: 1.5rem;
font-weight: bold;
}
.dashboard-stat-card {
transition: transform 0.2s ease, box-shadow 0.2s ease;
cursor: pointer;
}
.dashboard-stat-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
</style>
{{end}}
@@ -83,56 +93,64 @@
<div class="row g-4 mb-4">
<div class="col-6 col-md-3">
<div class="card bg-primary text-white h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-white-50">未完了の課題</h6>
<h2 class="mb-0">{{.stats.TotalPending}}</h2>
<a href="/assignments?filter=pending" class="text-decoration-none">
<div class="card bg-primary text-white h-100 dashboard-stat-card">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-white-50">未完了の課題</h6>
<h2 class="mb-0">{{.stats.TotalPending}}</h2>
</div>
<i class="bi bi-list-task display-4 opacity-50"></i>
</div>
<i class="bi bi-list-task display-4 opacity-50"></i>
</div>
</div>
</div>
</a>
</div>
<div class="col-6 col-md-3">
<div class="card bg-warning text-dark h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-dark-50">今日が期限</h6>
<h2 class="mb-0">{{.stats.DueToday}}</h2>
<a href="/assignments?filter=due_today" class="text-decoration-none">
<div class="card bg-warning text-dark h-100 dashboard-stat-card">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-dark-50">今日が期限</h6>
<h2 class="mb-0">{{.stats.DueToday}}</h2>
</div>
<i class="bi bi-calendar-event display-4 opacity-50"></i>
</div>
<i class="bi bi-calendar-event display-4 opacity-50"></i>
</div>
</div>
</div>
</a>
</div>
<div class="col-6 col-md-3">
<div class="card bg-info text-white h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-white-50">今週が期限</h6>
<h2 class="mb-0">{{.stats.DueThisWeek}}</h2>
<a href="/assignments?filter=due_this_week" class="text-decoration-none">
<div class="card bg-info text-white h-100 dashboard-stat-card">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-white-50">今週が期限</h6>
<h2 class="mb-0">{{.stats.DueThisWeek}}</h2>
</div>
<i class="bi bi-calendar-week display-4 opacity-50"></i>
</div>
<i class="bi bi-calendar-week display-4 opacity-50"></i>
</div>
</div>
</div>
</a>
</div>
<div class="col-6 col-md-3">
<div class="card bg-danger text-white h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-white-50">期限切れ</h6>
<h2 class="mb-0">{{.stats.Overdue}}</h2>
<a href="/assignments?filter=overdue" class="text-decoration-none">
<div class="card bg-danger text-white h-100 dashboard-stat-card">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-white-50">期限切れ</h6>
<h2 class="mb-0">{{.stats.Overdue}}</h2>
</div>
<i class="bi bi-exclamation-triangle display-4 opacity-50"></i>
</div>
<i class="bi bi-exclamation-triangle display-4 opacity-50"></i>
</div>
</div>
</div>
</a>
</div>
</div>