Skip to content

Commit 00510df

Browse files
rtcode337claude
andauthored
訪問日の「今日」を日付固定せず保存する (#51)
絞り込みの訪問日(訪問順の経路の対象日)で「今日」を選んでいるとき、 localStorageへ具体的な日付ではなく文字列"today"で保存し、読み込み時に その日のtodayKey()へ解決する。日付のまま保存すると、翌日に地図を開いた とき前日が選ばれた状態で復元されてしまうため。 Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent e4036c7 commit 00510df

2 files changed

Lines changed: 26 additions & 8 deletions

File tree

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ GitHub Actions(`.github/workflows/docker-publish.yml`)がビルド時に`<JST日
152152

153153
`SpotFilters``visitedDate`(`YYYY-MM-DD`のローカル日付)は**絞り込みではなく、地図で「訪問順の経路」を描く対象日**。選んだ日に訪問したスポットを訪問時刻の昇順に緑の矢印で結ぶための日で、`null`=経路を表示しない、既定はその日(今日)。**地図専用**で、スポット一覧(`SpotsView`)は経路を持たないため訪問日のUI自体を出さない(`passesFilters``visitedDate`を見ない。旧・第5引数の`visitedDates`は廃止)。
154154

155-
絞り込みモーダルの「訪問日」セレクト(`MapView`。重ね表示セクションと同じ`border-t`区切り線を上に置く)の選択肢は、先頭が常に「今日」、次が「表示しない」(=`null`)、続けて自分の訪問記録がある他の日(新しい順。`visitDates`/`visitDateOptions`。表示中の種別のスポットへの訪問がある日のみ。選択中の日が一覧に無くても選択を保てるよう残す)。既定値は今日。「表示しない」(`null`)は`saveFilters`が文字列`"none"`で保存し、`loadSavedFilters`は`"none"`のときだけ`null`=表示しないにする。日付はその日、それ以外(旧仕様の絞り込みだった頃の`null`・キー欠落・不正値)は今日に倒すため、**既存ユーザーも初回から今日の経路が出る**(`todayKey`/`defaultMapFilters`)。セレクトで日を選んだとき(`handleSelectVisitDate`)は、対象日をセットしたうえで**その日の訪問順の経路全体が画面に収まるよう`fitBounds`する**(1地点だけの日はmaxZoomまで寄る。経路が0件・「表示しない」のときは地図を動かさない)。ユーザーが明示的に選んだときだけ移動し、マウント時の既定(今日)の復元では移動しない。日付キーへの変換は`toVisitDateKey`(`visits.visited_on`はtimestamptzでUTC文字列のため、**必ずローカル時刻で日を切る** — UTCのまま切ると日本時間の朝9時前の訪問が前日になる)。
155+
絞り込みモーダルの「訪問日」セレクト(`MapView`。重ね表示セクションと同じ`border-t`区切り線を上に置く)の選択肢は、先頭が常に「今日」、次が「表示しない」(=`null`)、続けて自分の訪問記録がある他の日(新しい順。`visitDates`/`visitDateOptions`。表示中の種別のスポットへの訪問がある日のみ。選択中の日が一覧に無くても選択を保てるよう残す)。既定値は今日。「表示しない」(`null`)は`saveFilters`が文字列`"none"`で保存し、`loadSavedFilters`は`"none"`のときだけ`null`=表示しないにする。**「今日」(値が`todayKey()`と一致)は具体的な日付ではなく文字列`"today"`で保存し、読み込み時にその日の今日へ解決する**(日付のまま保存すると翌日に開いたとき前日が選ばれた状態で復元されてしまうため)。日付はその日、それ以外(旧仕様の絞り込みだった頃の`null`・キー欠落・不正値)は今日に倒すため、**既存ユーザーも初回から今日の経路が出る**(`todayKey`/`defaultMapFilters`)。セレクトで日を選んだとき(`handleSelectVisitDate`)は、対象日をセットしたうえで**その日の訪問順の経路全体が画面に収まるよう`fitBounds`する**(1地点だけの日はmaxZoomまで寄る。経路が0件・「表示しない」のときは地図を動かさない)。ユーザーが明示的に選んだときだけ移動し、マウント時の既定(今日)の復元では移動しない。日付キーへの変換は`toVisitDateKey`(`visits.visited_on`はtimestamptzでUTC文字列のため、**必ずローカル時刻で日を切る** — UTCのまま切ると日本時間の朝9時前の訪問が前日になる)。
156156

157157
訪問日が選ばれているとき、`MapView`は**その日の訪問記録を訪問時刻の昇順に矢印で結んだ「訪問順の経路」**を描く(`buildVisitPath`)。ルートCSVのルートと同じ`spot-routes`ソース・同じ線/矢印レイヤーに載せるだけなので描画コードは共用で、色だけ`VISIT_PATH_COLOR`(緑`#16a34a`=訪問済みピンの塗りと同じ)にしてルートと区別する。同じスポットへの再訪はそのまま複数回経由地として現れる(行って戻る線になる)が、連続する同じスポットへの訪問は長さ0の線分になり矢印の向きが定まらないためまとめる。他の種別の訪問記録・日時不明の訪問は除外する。**この経路上のスポット(`pathIds`)は、シリーズ・カテゴリ・訪問状況の絞り込みで外れていても必ずピンを表示する**(絞り込みではなくその日の訪問を辿るための表示のため全条件を免除。ルートCSVの経由地はシリーズ・カテゴリのみ免除で訪問状況は適用する点と対照的)。
158158

components/MapView.tsx

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -806,8 +806,10 @@ function effectiveIsolate(filters: SpotFilters): "visit" | "plan" | null {
806806
* 保存済みの絞り込み条件を読む。未保存・不正値は既定(訪問順の経路=今日)を返す。
807807
* `visitedDate`は絞り込みではなく訪問順の経路の対象日で、既定は今日。「表示しない」は
808808
* 保存時に文字列`"none"`で書く(下記`saveFilters`)ため、`"none"`のときだけnull=表示
809-
* しないにする。旧仕様の保存値(絞り込みだった頃のnull・日付、キー欠落)は「明示的な
810-
* 表示しない」ではないので今日に倒す(既存ユーザーも初回から今日の経路が出る)。
809+
* しないにする。「今日」は`"today"`で保存されるので、読み込み時のその日の`todayKey()`に
810+
* 解決する(日付を固定しないので、翌日に開いてもその日が今日として選ばれる)。旧仕様の
811+
* 保存値(絞り込みだった頃のnull・日付、キー欠落)は「明示的な表示しない」ではないので
812+
* 今日に倒す(既存ユーザーも初回から今日の経路が出る)。
811813
*/
812814
function loadSavedFilters(typeKey: string): SpotFilters {
813815
if (typeof localStorage === "undefined") return defaultMapFilters();
@@ -831,9 +833,14 @@ function loadSavedFilters(typeKey: string): SpotFilters {
831833
// 空(「すべて」チップがあった頃の保存値・キー欠落)は既定=未訪問のみに倒す
832834
// (現行UIに空選択の状態は無い。全件表示は両方選択で保存される)
833835
visited: visited.length > 0 ? visited : [...DEFAULT_FILTERS.visited],
834-
// "none"=表示しない、日付=その日、それ以外(旧null・キー欠落など)=今日
836+
// "none"=表示しない、"today"=(その日ではなく)常に今日、日付=その日、
837+
// それ以外(旧null・キー欠落など)=今日
835838
visitedDate:
836-
obj.visitedDate === "none" ? null : date(obj.visitedDate) ?? todayKey(),
839+
obj.visitedDate === "none"
840+
? null
841+
: obj.visitedDate === "today"
842+
? todayKey()
843+
: date(obj.visitedDate) ?? todayKey(),
837844
// 訪問予定リストの経路対象(そのリストが今も存在するかは描画側で解決する)
838845
planListId: typeof obj.planListId === "string" ? obj.planListId : null,
839846
// キー自体が無い保存データ(この設定の追加前に保存されたもの)は既定のオン扱い
@@ -849,9 +856,20 @@ function loadSavedFilters(typeKey: string): SpotFilters {
849856

850857
function saveFilters(typeKey: string, filters: SpotFilters) {
851858
try {
852-
// 「表示しない」(null)は旧仕様の「絞り込みなしのnull」と区別するため"none"で保存する
853-
// (でないと既存ユーザーの旧nullも「表示しない」に見えてしまう。loadSavedFilters参照)
854-
const stored = { ...filters, visitedDate: filters.visitedDate ?? "none" };
859+
// visitedDate の保存表現:
860+
// - null(表示しない) → "none"(旧仕様の「絞り込みなしのnull」と区別。loadSavedFilters参照)
861+
// - 今日(todayKey()と一致) → "today"(具体的な日付ではなく「今日」の意図で保存する。
862+
// でないと日付が固定され、翌日に前日が選ばれた状態で復元されてしまう。「今日」は
863+
// セレクトの選択肢として today のみで、others からは today を除いているため、
864+
// visitedDate が todayKey() と一致するのは「今日」を選んだときだけと判断できる)
865+
// - それ以外の具体的な日付 → その日付をそのまま保存
866+
const storedVisitedDate =
867+
filters.visitedDate == null
868+
? "none"
869+
: filters.visitedDate === todayKey()
870+
? "today"
871+
: filters.visitedDate;
872+
const stored = { ...filters, visitedDate: storedVisitedDate };
855873
localStorage.setItem(FILTERS_STORAGE_PREFIX + typeKey, JSON.stringify(stored));
856874
} catch {
857875
// プライベートブラウズ等で保存できなくても絞り込み自体は動かす

0 commit comments

Comments
 (0)