Skip to content

Commit 6236643

Browse files
committed
訪問日の「過去1年」を「過去1年だけを表示」にして、これだけを表示の隣へ
期間を選ぶだけのボタンをやめ、押すと対象日を1年前〜今日にしてから絞り(isolate)まで 掛けるトグルにした。置き場も日付の行から見出し行の「これだけを表示」の隣へ移した。 isolate に値は増やしていない。2つは同じ絞りの入り口が2つあるだけで、違うのは対象の 期間だけなので、押されている側は対象日がちょうど1年前〜今日か(isPastYearRange)で 見分ける。条件が互いの否定になっているため排他は自動的に成立する。値を増やすと、 絞り込みを効かせるかの判定や保存値の読み込みまで、期間の違いでしかないものを各所で 分岐させることになる。 解除したときは対象日も既定(今日)へ戻す。絞りだけ解いて期間を1年のまま残すと、 1年ぶんの訪問が1本の訪問順の経路として繋がり、地図が矢印だらけになって読めなくなる。 日付の行とカレンダーにあった「過去1年」は消した。残すと「期間だけ変えるほう」と 「絞りも掛けるほう」が並んで紛らわしい。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 94ebfb2 commit 6236643

3 files changed

Lines changed: 57 additions & 32 deletions

File tree

CLAUDE.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,11 @@ PATCH `/api/spot-types/[id]`は`series_styles`・`categories`を保存前に検
366366

367367
選び方は**カレンダー**(`components/VisitDateCalendar.tsx`)。絞り込みモーダルの訪問日セクションには**選択中の日(期間)を出すボタン**だけを置き、押すと**カレンダーを別モーダル(z-[60]。絞り込みモーダルのz-50の上)で開く** —— 絞り込みモーダルにカレンダーを直に置くと、他の条件を見るのに毎回その分スクロールすることになるため。**カレンダーは日を選んでも閉じない**(期間は2回のタップで決まるので、1回目で閉じると期間を選べない)。選択はその場で反映されるので、閉じる操作は「閉じる」だけでよい。
368368

369-
**よく使う期間はカレンダーを開かずに選べる。** 訪問日セクションとカレンダーの両方に**「今日」「過去1年」「表示しない」**を並べてある(`MapView``visitDateOptions`)。「過去1年」は**1年前の同じ日〜今日**の期間で、カレンダーだと開始月まで12回さかのぼって2回タップすることになるため置いた。**1年前の日付は`Date`に年だけ引かせる**ので、2月29日は3月1日に送られる(閏年でない年に2月29日は無い)——絞り込みの範囲としては1日の差なので、月末を特別扱いはしない。
369+
**よく使う期間はカレンダーを開かずに選べる。** 訪問日セクションとカレンダーに**「今日」「表示しない」**を並べ、見出し行の「これだけを表示」の隣に**「過去1年だけを表示」**を置いてある(`MapView``visitDateOptions`)。**1年前の日付は`Date`に年だけ引かせる**ので、2月29日は3月1日に送られる(閏年でない年に2月29日は無い)——絞り込みの範囲としては1日の差なので、月末を特別扱いはしない。
370+
371+
**「これだけを表示」と「過去1年だけを表示」は、同じ絞り(`isolate: "visit"`)の入り口が2つあるだけ**で、違うのは対象の期間だけ。押すと対象日を**1年前〜今日**にしてから絞りを掛けるので、期間を選ぶ操作が要らない(カレンダーだと開始月まで12回さかのぼって2回タップすることになる)。**`isolate`に値を増やしていない** —— 増やすと絞り込みを効かせるかの判定(`skipFiltersInIsolate`)や保存値の読み込みまで、期間の違いでしかないものを各所で分岐させることになる。期間は`visitedDate`/`visitedDateTo`が既に持っているので、**押されている側は対象日がちょうど1年前〜今日か(`isPastYearRange`)で見分ける**。この作りのおかげで2つは自動的に排他になる(条件が互いの否定になっている)。カレンダーで偶然その期間を選んだときも「過去1年だけを表示」が点くが、実際にその期間なので嘘にはならない。
372+
373+
**「過去1年だけを表示」を解除すると、対象日も既定(今日)へ戻す。** 絞りだけ解いて期間を1年のまま残すと、**1年ぶんの訪問が1本の訪問順の経路として繋がり**、地図が矢印だらけになって読めなくなる。
370374

371375
**訪問記録のある日には日付の下に緑の点**を打つ(`visitDateSet`。どの日に記録があるか分からないまま総当たりで選ぶことになるのを避けるため。**他のスポット種別への訪問も数える** — 経路が種別をまたぐようになったので、その日を落とすと辿れない)。1回目のタップで開始日、2回目で終了日。既に期間が決まっている状態でのタップは新しい開始日として選び直し(範囲を狭めるのにリセットを挟まずに済む)、開始日より前をタップしたときはその日を開始日にして元の開始日を終了日にする(前方向にも伸ばせる)。同じ日を2回タップしても単日のまま。「今日」「表示しない」はよく使うので、カレンダーの中と絞り込みモーダルの両方に置く。既定値は今日。かつてはセレクト(今日 / 表示しない / 訪問のある日の一覧)だったが、期間指定とデータのある日の可視化のためカレンダーに変えた。「表示しない」(`null`)は`saveFilters`が文字列`"none"`で保存し、`loadSavedFilters`は`"none"`のときだけ`null`=表示しないにする。**「今日」(値が`todayKey()`と一致)は具体的な日付ではなく文字列`"today"`で保存し、読み込み時にその日の今日へ解決する**(日付のまま保存すると翌日に開いたとき前日が選ばれた状態で復元されてしまうため)。日付はその日、それ以外(旧仕様の絞り込みだった頃の`null`・キー欠落・不正値)は今日に倒すため、**既存ユーザーも初回から今日の経路が出る**(`todayKey`/`defaultMapFilters`)。終了日(`visitedDateTo`)は**「今日」のような相対表現を持たず具体的な日付でだけ保存する**(終了日だけ動くと期間の長さが日をまたぐたびに変わってしまうため)。カレンダーで日を選んだとき(`handleSelectVisitDate`)は、対象日(期間)をセットしたうえで**その経路全体が画面に収まるよう`fitBounds`する**(1地点だけならmaxZoomまで寄る。経路が0件・「表示しない」のときは地図を動かさない)。開始日を`null`にするときは終了日も一緒に落とす(残っていると次に日を選んだとき意図しない期間になる)。ユーザーが明示的に選んだときだけ移動し、マウント時の既定(今日)の復元では移動しない。日付キーへの変換は`toVisitDateKey`(`visits.visited_on`はtimestamptzでUTC文字列のため、**必ずローカル時刻で日を切る** — UTCのまま切ると日本時間の朝9時前の訪問が前日になる)。
372376

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
| 機能 | 説明 |
2222
|---|---|
23-
| **絞り込み** | ランク・シリーズ・訪問状態・カテゴリ・訪問日で絞れる。訪問日は「今日」「過去1年」をカレンダーを開かずに選べる |
23+
| **絞り込み** | ランク・シリーズ・訪問状態・カテゴリ・訪問日で絞れる。訪問日は「今日」をカレンダーを開かずに選べ、**「過去1年だけを表示」**でこの1年に訪問したスポットだけに絞れる |
2424
| **見た目の3軸** | **ランク**(A〜E。色と大きさ)・**シリーズ**(1スポットに1つ。ピンの中のアイコンと形)・**カテゴリ**(複数可。絞り込み専用) |
2525
| **訪問予定** | 行きたい場所のブックマーク。訪問を記録すると自動的に外れる |
2626
| **訪問予定リスト** | 複数スポットを順序付きでまとめた旅程。地図に紫の矢印で経路を描き、Googleマップの経路検索へそのまま渡せる。回り終わったリストは**アーカイブ**して一覧から下げられる(中身は残り、スポット画面の「アーカイブ」から読み直せる) |

components/MapView.tsx

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,6 +1564,18 @@ export default function MapView({
15641564
() => ({ today: todayKey(), oneYearAgo: oneYearAgoKey() }),
15651565
[]
15661566
);
1567+
// 訪問日の「これだけを表示」中か。「これだけを表示」と「過去1年だけを表示」は
1568+
// 同じ絞り(isolate: "visit")の入り口が2つあるだけで、違うのは対象の期間。
1569+
// **isolateに値を増やしていない** —— 増やすと絞り込みを効かせるかの判定
1570+
// (skipFiltersInIsolate)や保存値の読み込みまで、期間の違いでしかないものを
1571+
// 各所で分岐させることになる。期間は visitedDate/visitedDateTo が既に持っている
1572+
const isolatingVisit = filters.isolate === "visit";
1573+
// 対象日がちょうど「1年前〜今日」か。押されているボタンをこれで見分ける
1574+
// (カレンダーで同じ期間を選んだときも「過去1年だけを表示」が点くが、
1575+
// 実際にその期間なので嘘にはならない)
1576+
const isPastYearRange =
1577+
filters.visitedDate === visitDateOptions.oneYearAgo &&
1578+
filters.visitedDateTo === visitDateOptions.today;
15671579
// 変更のたびにlocalStorageへも書き込む(次に地図を開いたときの復元用)
15681580
const setFilters = useCallback(
15691581
(next: SpotFilters) => {
@@ -3762,18 +3774,6 @@ export default function MapView({
37623774
>
37633775
今日
37643776
</button>
3765-
<button
3766-
type="button"
3767-
onClick={() =>
3768-
handleSelectVisitDate(
3769-
visitDateOptions.oneYearAgo,
3770-
visitDateOptions.today
3771-
)
3772-
}
3773-
className="flex-1 rounded-lg border border-gray-300 py-2 text-sm"
3774-
>
3775-
過去1年
3776-
</button>
37773777
<button
37783778
type="button"
37793779
onClick={() => handleSelectVisitDate(null, null)}
@@ -3835,25 +3835,61 @@ export default function MapView({
38353835
</HelpTip>
38363836
</p>
38373837
<div className="flex shrink-0 items-center gap-1.5">
3838+
{/* 「これだけを表示」と「過去1年だけを表示」は同じ絞り(isolate)の
3839+
入り口が2つあるだけで、違うのは対象の期間。どちらか一方しか
3840+
点かないので、押されている側を見れば期間が読める */}
38383841
{/* その日のスポットだけに絞る(他のスポット・ルート・訪問予定リストは隠す) */}
38393842
<button
38403843
type="button"
38413844
disabled={!filters.visitedDate}
3842-
aria-pressed={filters.isolate === "visit"}
3845+
aria-pressed={isolatingVisit && !isPastYearRange}
38433846
onClick={() =>
38443847
setFilters({
38453848
...filters,
3846-
isolate: filters.isolate === "visit" ? null : "visit",
3849+
isolate: isolatingVisit ? null : "visit",
38473850
})
38483851
}
38493852
className={`shrink-0 rounded-full border px-2.5 py-0.5 text-xs font-medium disabled:opacity-40 ${
3850-
filters.isolate === "visit"
3853+
isolatingVisit && !isPastYearRange
38513854
? "border-blue-600 bg-blue-600 text-white"
38523855
: "border-gray-300 bg-white text-gray-500"
38533856
}`}
38543857
>
38553858
これだけを表示
38563859
</button>
3860+
{/* 過去1年に訪問したスポットだけに絞る。対象日を1年前〜今日にしてから
3861+
同じ絞りを掛けるので、押すだけで期間の選択が要らない
3862+
(カレンダーだと開始月まで12回さかのぼることになる)。
3863+
解除すると対象日も既定=今日へ戻す —— 期間だけが1年のまま残ると、
3864+
1年ぶんの訪問が1本の経路として繋がって読めなくなる */}
3865+
<button
3866+
type="button"
3867+
aria-pressed={isolatingVisit && isPastYearRange}
3868+
onClick={() =>
3869+
setFilters(
3870+
isolatingVisit && isPastYearRange
3871+
? {
3872+
...filters,
3873+
visitedDate: visitDateOptions.today,
3874+
visitedDateTo: null,
3875+
isolate: null,
3876+
}
3877+
: {
3878+
...filters,
3879+
visitedDate: visitDateOptions.oneYearAgo,
3880+
visitedDateTo: visitDateOptions.today,
3881+
isolate: "visit",
3882+
}
3883+
)
3884+
}
3885+
className={`shrink-0 rounded-full border px-2.5 py-0.5 text-xs font-medium ${
3886+
isolatingVisit && isPastYearRange
3887+
? "border-blue-600 bg-blue-600 text-white"
3888+
: "border-gray-300 bg-white text-gray-500"
3889+
}`}
3890+
>
3891+
過去1年だけを表示
3892+
</button>
38573893
{/* このセクションだけのリセット(対象日を既定=今日に戻し、
38583894
「これだけを表示」も解除する) */}
38593895
<SectionResetButton
@@ -3908,21 +3944,6 @@ export default function MapView({
39083944
>
39093945
今日
39103946
</button>
3911-
{/* よく使う期間はカレンダーを開かずに選べるようにする。
3912-
1年ぶんを選ぶのに、カレンダーだと開始月まで12回さかのぼって
3913-
2回タップすることになるため */}
3914-
<button
3915-
type="button"
3916-
onClick={() =>
3917-
handleSelectVisitDate(
3918-
visitDateOptions.oneYearAgo,
3919-
visitDateOptions.today
3920-
)
3921-
}
3922-
className="rounded-full border border-gray-300 px-2.5 py-1 text-xs text-gray-600"
3923-
>
3924-
過去1年
3925-
</button>
39263947
<button
39273948
type="button"
39283949
onClick={() => handleSelectVisitDate(null, null)}

0 commit comments

Comments
 (0)