Skip to content

Commit 6aa56ca

Browse files
TinyKittenclaude
andauthored
プリセットから方面選択モーダルを開いた時に両方面のカードを表示する (#5584)
* プリセットから方面選択モーダルを開いた時に両方面のカードを表示する Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * テストのhooksモックにusePresetStopsを追加 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f8ee83f commit 6aa56ca

File tree

7 files changed

+487
-23
lines changed

7 files changed

+487
-23
lines changed

src/components/SelectBoundModal.render.test.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ jest.mock('~/hooks', () => ({
2828
save: jest.fn(),
2929
remove: jest.fn(),
3030
})),
31+
usePresetStops: jest.fn(() => ({
32+
presetOrigin: null,
33+
presetStops: undefined,
34+
nearestPresetStation: undefined,
35+
resolvePresetDirection: jest.fn(() => 'INBOUND'),
36+
})),
3137
}));
3238

3339
jest.mock('~/translation', () => ({

src/components/SelectBoundModal.tsx

Lines changed: 99 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
useBounds,
1212
useGetStationsWithTermination,
1313
useLoopLine,
14+
usePresetStops,
1415
useSavedRoutes,
1516
} from '~/hooks';
1617
import { directionToDirectionName, type LineDirection } from '~/models/Bound';
@@ -126,6 +127,7 @@ export const SelectBoundModal: React.FC<Props> = ({
126127
const navigation = useNavigation();
127128
const [stationAtom, setStationState] = useAtom(stationState);
128129
const {
130+
station: confirmedStation,
129131
pendingStation: station,
130132
pendingStations: stations,
131133
wantedDestination,
@@ -214,18 +216,31 @@ export const SelectBoundModal: React.FC<Props> = ({
214216
navigation.navigate('Main' as never);
215217
}, [navigation]);
216218

219+
const {
220+
presetOrigin,
221+
presetStops,
222+
nearestPresetStation,
223+
resolvePresetDirection,
224+
} = usePresetStops({
225+
savedRouteDirection: savedRoute?.direction,
226+
stations,
227+
wantedDestination,
228+
confirmedStation,
229+
});
230+
217231
const handleBoundSelected = useCallback(
218232
(
219233
selectedStation: Station,
220234
direction: LineDirection,
221-
terminateBySelectedStation = false
235+
terminateBySelectedStation = false,
236+
stopsOverride?: Station[]
222237
) => {
223238
if (isTransitioningRef.current) return;
224239
isTransitioningRef.current = true;
225240
setIsTransitioning(true);
226241

227-
let stops = stations;
228-
if (terminateBySelectedStation && effectiveStation) {
242+
let stops = stopsOverride ?? stations;
243+
if (!stopsOverride && terminateBySelectedStation && effectiveStation) {
229244
const destIdx = stations.findIndex(
230245
(s) => s.groupId === selectedStation.groupId
231246
);
@@ -240,23 +255,34 @@ export const SelectBoundModal: React.FC<Props> = ({
240255
}
241256
}
242257

258+
const effectiveDirection = stopsOverride
259+
? resolvePresetDirection(selectedStation, stops)
260+
: direction;
261+
262+
const departureFallback =
263+
effectiveDirection === 'INBOUND' ? stops[0] : stops.at(-1);
264+
const startStation = stopsOverride
265+
? (nearestPresetStation ?? departureFallback ?? effectiveStation)
266+
: effectiveStation;
267+
243268
setLineState((prev) => ({
244269
...prev,
245270
selectedLine: line,
246271
pendingLine: null,
247272
}));
248273
setStationState((prev) => ({
249274
...prev,
250-
station: effectiveStation,
275+
station: startStation,
251276
stations: stops,
252277
selectedBound:
253-
direction === 'INBOUND' ? stops[stops.length - 1] : stops[0],
254-
selectedDirection: direction,
278+
effectiveDirection === 'INBOUND' ? (stops.at(-1) ?? null) : stops[0],
279+
selectedDirection: effectiveDirection,
255280
pendingStation: null,
256281
pendingStations: [],
257-
wantedDestination: terminateBySelectedStation
258-
? prev.wantedDestination
259-
: null,
282+
wantedDestination:
283+
terminateBySelectedStation || stopsOverride
284+
? prev.wantedDestination
285+
: null,
260286
}));
261287
setNavigationState((prev) => ({
262288
...prev,
@@ -269,6 +295,8 @@ export const SelectBoundModal: React.FC<Props> = ({
269295
[
270296
navigateToMain,
271297
effectiveStation,
298+
nearestPresetStation,
299+
resolvePresetDirection,
272300
stations,
273301
line,
274302
pendingTrainType,
@@ -362,9 +390,7 @@ export const SelectBoundModal: React.FC<Props> = ({
362390
};
363391
const finalStop =
364392
wantedDestination ??
365-
(direction === 'INBOUND'
366-
? boundStations[0]
367-
: boundStations[boundStations.length - 1]);
393+
(direction === 'INBOUND' ? boundStations[0] : boundStations.at(-1));
368394

369395
const lineForCard = finalStop?.line;
370396
const trainTypeForCard = finalStop?.trainType;
@@ -403,27 +429,34 @@ export const SelectBoundModal: React.FC<Props> = ({
403429
(s) => s.groupId === wantedDestination.groupId
404430
);
405431

406-
if (
407-
currentStationIndex === -1 ||
408-
wantedStationIndex === -1 ||
409-
currentStationIndex === wantedStationIndex
410-
) {
432+
if (wantedStationIndex === -1) {
411433
return <></>;
412434
}
413435

414-
const dir: LineDirection =
415-
currentStationIndex < wantedStationIndex ? 'INBOUND' : 'OUTBOUND';
436+
// 現在駅が経路内にない場合は savedRoute.direction から方向を決定
437+
const canDetermineFromIndex =
438+
currentStationIndex !== -1 &&
439+
currentStationIndex !== wantedStationIndex;
440+
let dir: LineDirection = savedRoute?.direction ?? 'INBOUND';
441+
if (canDetermineFromIndex) {
442+
dir =
443+
currentStationIndex < wantedStationIndex ? 'INBOUND' : 'OUTBOUND';
444+
}
416445

446+
// wantedDestination 方向のカード
417447
if (direction === dir && line) {
418-
const title = isLoopLine
419-
? loopLineDirectionText(direction)
420-
: normalLineDirectionText(boundStations);
448+
const title = normalLineDirectionText(boundStations);
421449
const subtitle = buildSubtitle(lineForCard, trainTypeForCard) ?? '';
422450
return (
423451
<CommonCard
424452
line={lineForCard ?? line}
425453
onPress={() =>
426-
handleBoundSelected(wantedDestination, dir, !!wantedDestination)
454+
handleBoundSelected(
455+
wantedDestination,
456+
dir,
457+
!!wantedDestination,
458+
presetStops
459+
)
427460
}
428461
disabled={isTransitioning}
429462
loading={isTransitioning}
@@ -433,6 +466,45 @@ export const SelectBoundModal: React.FC<Props> = ({
433466
/>
434467
);
435468
}
469+
470+
// 逆方向カード: presetOrigin がない or GPS確定駅が起点と同じ場合は非表示
471+
if (
472+
!presetOrigin ||
473+
confirmedStation?.groupId === presetOrigin.groupId
474+
) {
475+
return <></>;
476+
}
477+
478+
if (boundStations.length) {
479+
const reverseLineForCard =
480+
(presetOrigin.line as Line | undefined) ?? lineForCard;
481+
const reverseSubtitle =
482+
buildSubtitle(reverseLineForCard, presetOrigin.trainType) ?? '';
483+
const reverseDirForNav: LineDirection =
484+
savedRoute?.direction === 'INBOUND' ? 'OUTBOUND' : 'INBOUND';
485+
return (
486+
<CommonCard
487+
onPress={() =>
488+
handleBoundSelected(
489+
presetOrigin,
490+
reverseDirForNav,
491+
false,
492+
presetStops
493+
)
494+
}
495+
disabled={isTransitioning}
496+
loading={isTransitioning}
497+
line={reverseLineForCard}
498+
title={
499+
isJapanese
500+
? `${presetOrigin.name}方面`
501+
: `for ${presetOrigin.nameRoman ?? ''}`
502+
}
503+
subtitle={reverseSubtitle}
504+
targetStation={presetOrigin}
505+
/>
506+
);
507+
}
436508
return <></>;
437509
}
438510

@@ -478,6 +550,10 @@ export const SelectBoundModal: React.FC<Props> = ({
478550
line,
479551
loopLineDirectionText,
480552
normalLineDirectionText,
553+
savedRoute?.direction,
554+
confirmedStation?.groupId,
555+
presetOrigin,
556+
presetStops,
481557
]
482558
);
483559

src/hooks/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export { useNextStation } from './useNextStation';
4848
export { useNextTrainType } from './useNextTrainType';
4949
export { useNumbering } from './useNumbering';
5050
export { usePresetCarouselData } from './usePresetCarouselData';
51+
export { usePresetStops } from './usePresetStops';
5152
export { usePrevious } from './usePrevious';
5253
export { usePreviousStation } from './usePreviousStation';
5354
export { useRefreshLeftStations } from './useRefreshLeftStations';

0 commit comments

Comments
 (0)