Skip to content

Commit

Permalink
feat: group trip suggestions by date
Browse files Browse the repository at this point in the history
  • Loading branch information
rosvik committed Jan 14, 2025
1 parent c22377a commit 649581f
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 30 deletions.
75 changes: 45 additions & 30 deletions src/Trips/TripsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { Fragment } from "react";
import { Fragment, useCallback, useEffect, useState, useRef } from "react";
import { Feature, Leg, TripPattern } from "../types";
import { ActionPanel, Action, Color, List, Icon } from "@raycast/api";
import { fetchTrip } from "../api";
import { useCallback, useEffect, useState } from "react";
import {
getTransportIcon,
formatAsClock,
formatTimeDifferenceAsClock,
formatMetersToHuman,
formatDestinationDisplay,
formatAsDate,
} from "../utils";

type Props = {
origin: Feature;
destination: Feature;
};
export default function TripsPage({ origin, destination }: Props) {
const [trips, setTrips] = useState<TripPattern[]>([]);
const trips = useRef<TripPattern[]>([]);
const [groupedTrips, setGroupedTrips] = useState<GroupedTrips>({});
const [isLoading, setIsLoading] = useState(true);
const [pageCursor, setPageCursor] = useState("");
const [isDetailVisible, setDetailVisible] = useState(false);
Expand All @@ -29,8 +30,8 @@ export default function TripsPage({ origin, destination }: Props) {
pageCursor,
})
.then((data) => {
const newTrips = trips?.concat(data.trip.tripPatterns);
setTrips(newTrips);
trips.current = trips.current?.concat(data.trip.tripPatterns);
setGroupedTrips(groupTripsByDate(trips.current));
setPageCursor(data.trip.nextPageCursor);
})
.finally(() => setIsLoading(false));
Expand All @@ -46,31 +47,34 @@ export default function TripsPage({ origin, destination }: Props) {
isShowingDetail={isDetailVisible}
searchBarPlaceholder={`From ${origin.properties.name} to ${destination.properties.name}...`}
>
{trips?.map((trip, idx) => (
<List.Item
detail={<List.Item.Detail metadata={<TripDetails trip={trip} />}></List.Item.Detail>}
actions={
<ActionPanel>
<Action
title="Toggle Details"
onAction={() => {
setDetailVisible(!isDetailVisible);
}}
/>
<Action
title="Load More"
// TODO: Remove this in favor of `pagination` returned from
// using the built-in useFetch/usePromise:
// https://developers.raycast.com/utilities/react-hooks/usefetch#pagination
onAction={getTrips}
/>
</ActionPanel>
}
title={`${formatAsClock(trip.expectedStartTime)} - ${formatAsClock(trip.expectedEndTime)}`}
// TODO: subtitle => "Little warning triangle if service disruptions are present"
accessories={getTripAccessories(trip, isDetailVisible)}
key={idx}
/>
{Object.entries(groupedTrips).map(([date, trips]) => (
<List.Section title={date === new Date().toDateString() ? "Today" : date} key={date}>
{trips.map((trip, idx) => (
<List.Item
detail={<List.Item.Detail metadata={<TripDetails trip={trip} />}></List.Item.Detail>}
actions={
<ActionPanel>
<Action
title="Toggle Details"
onAction={() => {
setDetailVisible(!isDetailVisible);
}}
/>
<Action
title="Load More"
// TODO: Remove this in favor of `pagination` returned from
// using the built-in useFetch/usePromise:
// https://developers.raycast.com/utilities/react-hooks/usefetch#pagination
onAction={getTrips}
/>
</ActionPanel>
}
title={`${formatAsClock(trip.expectedStartTime)} - ${formatAsClock(trip.expectedEndTime)}`}
accessories={getTripAccessories(trip, isDetailVisible)}
key={idx}
/>
))}
</List.Section>
))}
</List>
);
Expand Down Expand Up @@ -101,6 +105,17 @@ const TripDetails = ({ trip }: { trip: TripPattern }) => {
);
};

type GroupedTrips = Record<string, TripPattern[]>;
const groupTripsByDate = (trips: TripPattern[]) => {
let grouped: Record<string, TripPattern[]> = {};

Check failure on line 110 in src/Trips/TripsPage.tsx

View workflow job for this annotation

GitHub Actions / Lint and Build

'grouped' is never reassigned. Use 'const' instead
trips.forEach((trip) => {
const date = formatAsDate(trip.expectedStartTime);
grouped[date] = [...(grouped[date] || []), trip];
});
return grouped;
};

// TODO: Should add a warning triangle if service disruptions are present
const getTripAccessories = (
trip: TripPattern,
isDetailsVisible: boolean,
Expand Down
5 changes: 5 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ export function formatAsClock(isoString: string) {
return `${padTime(d.getHours())}:${padTime(d.getMinutes())}`;
}

export function formatAsDate(isoString: string) {
const d = new Date(isoString);
return d.toDateString();
}

export function formatMillisecondsToHuman(ms: number) {
const totalSeconds = Math.ceil(ms / 1000);
const minutes = Math.floor(totalSeconds / 60) % 60;
Expand Down

0 comments on commit 649581f

Please sign in to comment.