From 72c65c1df1105409006c9ed5f04cd315548ade9b Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Tue, 6 Feb 2024 19:54:33 +0000 Subject: [PATCH 01/71] Translated using Weblate (Spanish) Currently translated at 100.0% (557 of 557 strings) Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/es/ --- i18n/es.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/i18n/es.yml b/i18n/es.yml index 50484de4a..e62d23339 100644 --- a/i18n/es.yml +++ b/i18n/es.yml @@ -541,6 +541,7 @@ components: tripNotFound: No se encontró el viaje tripNotFoundDescription: Lo sentimos, no se encontró el viaje solicitado. tripNotifications: Notificaciones de viaje + deleteSavedTrip: Borrar viaje guardado SavedTripList: alertTag: "{alerta, plural, one {Ver una alerta} other {Ver # alertas}}" fromTo: De {from} al {to} From 6bfe97f6ccd666a2ae7e729b3be67cf855c8cdf9 Mon Sep 17 00:00:00 2001 From: amy-corson-ibigroup <115499534+amy-corson-ibigroup@users.noreply.github.com> Date: Fri, 9 Feb 2024 12:54:07 -0600 Subject: [PATCH 02/71] feat(SavedTripList): Updated trip card design --- i18n/en-US.yml | 8 +- .../monitored-trip/route-block-wrapper.tsx | 15 ++ .../user/monitored-trip/saved-trip-list.tsx | 90 ++++------ .../monitored-trip/trip-monitored-days.tsx | 73 ++++++++ .../user/monitored-trip/trip-summary-pane.tsx | 165 ++++++++++++++---- .../user/monitored-trip/trip-summary.tsx | 18 +- lib/components/user/styled.ts | 34 ++-- lib/components/user/types.ts | 6 +- 8 files changed, 283 insertions(+), 126 deletions(-) create mode 100644 lib/components/user/monitored-trip/route-block-wrapper.tsx create mode 100644 lib/components/user/monitored-trip/trip-monitored-days.tsx diff --git a/i18n/en-US.yml b/i18n/en-US.yml index b4fc69356..98d79d8ef 100644 --- a/i18n/en-US.yml +++ b/i18n/en-US.yml @@ -719,11 +719,9 @@ components: arriveAt: "Arrive at " leaveAt: "Leave at " TripSummaryPane: - happensOnDays: "Happens on: {days}" - notifications: >- - Notifications: {leadTimeInMinutes} min. before scheduled - departure - notificationsDisabled: "Notifications: Disabled" + happensOnDays: "Happens on: {days}" + notifications: "{leadTimeInMinutes} min. before scheduled departure" + notificationsDisabled: Notifications disabled TripTools: copyLink: Copy Link header: Trip Tools diff --git a/lib/components/user/monitored-trip/route-block-wrapper.tsx b/lib/components/user/monitored-trip/route-block-wrapper.tsx new file mode 100644 index 000000000..dbbb12fd2 --- /dev/null +++ b/lib/components/user/monitored-trip/route-block-wrapper.tsx @@ -0,0 +1,15 @@ +import { ComponentContext } from '../../../util/contexts' +import { Itinerary } from '@opentripplanner/types' +import React, { useContext } from 'react' + +interface Props { + itinerary: Itinerary +} +const RouteBlockWrapper = ({ itinerary }: Props) => { + // @ts-expect-error TODO: add ModesAndRoutes to ItineraryBody attribute of ComponentContext + const { ItineraryBody, LegIcon } = useContext(ComponentContext) + const ModesAndRoutes = ItineraryBody.ModesAndRoutes + return +} + +export default RouteBlockWrapper diff --git a/lib/components/user/monitored-trip/saved-trip-list.tsx b/lib/components/user/monitored-trip/saved-trip-list.tsx index bc8e2fdf8..ef0cc211f 100644 --- a/lib/components/user/monitored-trip/saved-trip-list.tsx +++ b/lib/components/user/monitored-trip/saved-trip-list.tsx @@ -1,9 +1,6 @@ -import { Button, Panel } from 'react-bootstrap' import { connect } from 'react-redux' import { FormattedMessage, injectIntl, IntlShape, useIntl } from 'react-intl' -import { Pause } from '@styled-icons/fa-solid/Pause' -import { PencilAlt } from '@styled-icons/fa-solid/PencilAlt' -import { Play } from '@styled-icons/fa-solid/Play' +import { Panel } from 'react-bootstrap' import { TriangleExclamation } from '@styled-icons/fa-solid/TriangleExclamation' import { withAuthenticationRequired } from '@auth0/auth0-react' import React, { Component } from 'react' @@ -11,15 +8,16 @@ import React, { Component } from 'react' import * as uiActions from '../../../actions/ui' import * as userActions from '../../../actions/user' import { AppReduxState } from '../../../util/state-types' -import { IconWithText } from '../../util/styledIcon' -import { InlineLoading } from '../../narrative/loading' +import { Edit } from '@styled-icons/fa-solid' +import { Icon, IconWithText } from '../../util/styledIcon' import { MonitoredTrip } from '../types' import { PageHeading, TripHeader, TripPanelAlert, TripPanelFooter, - TripPanelHeading + TripPanelHeading, + TripPannelTitle } from '../styled' import { RETURN_TO_CURRENT_ROUTE } from '../../../util/ui' import { TRIPS_PATH } from '../../../util/constants' @@ -30,6 +28,7 @@ import PageTitle from '../../util/page-title' import withLoggedInUserSupport from '../with-logged-in-user-support' import getRenderData from './trip-status-rendering-strategies' +import RouteBlockWrapper from './route-block-wrapper' import TripSummaryPane from './trip-summary-pane' interface ItemOwnProps { @@ -99,60 +98,37 @@ class TripListItem extends Component { return ( - {shouldRenderAlerts && ( - - - - - - )} - - {trip.tripName} - - {from.name}, - to: {to.name} - }} - /> - - + + + {trip.tripName} + + + + - - - - - - + + ) } diff --git a/lib/components/user/monitored-trip/trip-monitored-days.tsx b/lib/components/user/monitored-trip/trip-monitored-days.tsx new file mode 100644 index 000000000..66851081c --- /dev/null +++ b/lib/components/user/monitored-trip/trip-monitored-days.tsx @@ -0,0 +1,73 @@ +import { FormattedList, FormattedMessage } from 'react-intl' + +import FormattedDayOfWeek from '../../util/formatted-day-of-week' +import InvisibleA11yLabel from '../../util/invisible-a11y-label' +import React from 'react' +import Strong from '../../util/strong-text' + +import styled from 'styled-components' + +interface Props { + days: string[] +} + +const DayCircleContainer = styled.div` + display: flex; + gap: 4px; +` + +const MonitoredDay = styled.div<{ monitored: boolean }>` + width: 27px; + height: 27px; + border-radius: 50%; + background-color: ${(props) => (props.monitored ? '#4152a4' : 'transparent')}; + color: ${(props) => (props.monitored ? 'white' : 'inherit')}; + display: flex; + align-items: center; + justify-content: center; + text-transform: capitalize; +` + +const daysOfWeek = [ + 'monday', + 'tuesday', + 'wednesday', + 'thursday', + 'friday', + 'saturday', + 'sunday' +] + +const MonitoredDays = ({ days }: Props) => { + const monitoredDaysList = ( + ( + + ))} + /> + ) + const DayCircles = daysOfWeek.map((d) => { + const dayAbbrev = + d === 'thursday' || d === 'sunday' ? d.slice(0, 2) : d.charAt(0) + const monitored = days?.includes(d) + return ( + + {dayAbbrev} + + ) + }) + return ( + + {DayCircles} + + + + + ) +} + +export default MonitoredDays diff --git a/lib/components/user/monitored-trip/trip-summary-pane.tsx b/lib/components/user/monitored-trip/trip-summary-pane.tsx index d1fb81f03..a180e7243 100644 --- a/lib/components/user/monitored-trip/trip-summary-pane.tsx +++ b/lib/components/user/monitored-trip/trip-summary-pane.tsx @@ -1,21 +1,84 @@ -import { FormattedList, FormattedMessage } from 'react-intl' +import { Bell, BellSlash, Calendar } from '@styled-icons/fa-regular' +import { FormattedMessage } from 'react-intl' import React from 'react' import { dayFieldsToArray } from '../../../util/monitored-trip' import { MonitoredTripProps } from '../types' -import FormattedDayOfWeek from '../../util/formatted-day-of-week' -import Strong from '../../util/strong-text' +import LocationIcon from '@opentripplanner/location-icon' +import styled from 'styled-components' -import TripSummary from './trip-summary' +import { InlineLoading } from '../../narrative/loading' + +import MonitoredDays from './trip-monitored-days' /** * Displays the summary information of a monitored trip. */ + +const SavedTripBody = styled.div` + display: flex; + padding: 0 15px; +` + +const LocationDetails = styled.div` + width: 50%; + display: flex; + flex-direction: column; + gap: 10px; + align-items: start; + justify-content: center; + padding: 20px; + border-right: 1px solid #ddd; +` +const ItineraryDetails = styled.div` + display: flex; + justify-content: center; + padding: 20px; + width: 50%; +` +const TextWIcon = styled.div` + align-items: center; + justify-content: left; + display: flex; + gap: 7px; + + svg { + flex-shrink: 0; + } +` + +const TripDetailWithIcon = styled(TextWIcon)` + gap: 12px; + + svg { + width: 16px; + } +` + +const TripDetailsList = styled.ul` + list-style: none; + align-items: start; + justify-content: center; + display: flex; + flex-direction: column; + gap: 10px; + padding: 0; +` + +const ToggleNotificationButton = styled.button` + background: transparent; + border: none; + text-decoration: underline; +` + const TripSummaryPane = ({ - monitoredTrip + from, + handleTogglePauseMonitoring, + monitoredTrip, + pendingRequest, + to }: MonitoredTripProps): JSX.Element => { const { itinerary, leadTimeInMinutes } = monitoredTrip - if (!itinerary) { return (
@@ -23,39 +86,69 @@ const TripSummaryPane = ({
) } else { - const days = ( - ( - - ))} - /> - ) + const days = dayFieldsToArray(monitoredTrip) + + const testHandle = () => { + // @ts-expect-error hsdf + handleTogglePauseMonitoring() + } return ( - <> + {/* TODO: use the modern itinerary summary built for trip comparison. */} - -

- -

-

- {monitoredTrip.isActive ? ( - - ) : ( - - )} -

- + + + + {from?.name} + + + + {to?.name} + + + + + + + + + + {monitoredTrip.isActive ? : } + + {monitoredTrip.isActive ? ( + + ) : ( + + )} +
+ + {pendingRequest === 'pause' ? ( + /* Make loader fit */ + + ) : monitoredTrip.isActive ? ( + <> + + + ) : ( + <> + + + )} + +
+
+
+
+
) } } diff --git a/lib/components/user/monitored-trip/trip-summary.tsx b/lib/components/user/monitored-trip/trip-summary.tsx index ca5c700c9..8763f13f1 100644 --- a/lib/components/user/monitored-trip/trip-summary.tsx +++ b/lib/components/user/monitored-trip/trip-summary.tsx @@ -1,24 +1,20 @@ import { FormattedMessage, FormattedTime } from 'react-intl' -import React, { useContext } from 'react' +import React from 'react' import styled from 'styled-components' -import { ComponentContext } from '../../../util/contexts' import { MonitoredTripProps } from '../types' import FormattedDuration from '../../util/formatted-duration' import InvisibleA11yLabel from '../../util/invisible-a11y-label' -const SummaryContainer = styled.div` - margin-bottom: 10px; +const Divider = styled.span` + margin: 0 3px; ` const TripSummary = ({ monitoredTrip }: MonitoredTripProps): JSX.Element => { const { itinerary } = monitoredTrip const { duration, endTime, startTime } = itinerary - // @ts-expect-error TODO: add ModesAndRoutes to ItineraryBody attribute of ComponentContext - const { ItineraryBody, LegIcon } = useContext(ComponentContext) - const ModesAndRoutes = ItineraryBody.ModesAndRoutes return ( - + {/* Set up invisible "labels" for each itinerary field, and comma, so that the output of screen readers is more intelligible. */} @@ -29,11 +25,11 @@ const TripSummary = ({ monitoredTrip }: MonitoredTripProps): JSX.Element => { , - + + - - + ) } diff --git a/lib/components/user/styled.ts b/lib/components/user/styled.ts index c37f55287..2488c62d0 100644 --- a/lib/components/user/styled.ts +++ b/lib/components/user/styled.ts @@ -46,8 +46,25 @@ export const TripHeader = styled.h3` margin-top: 0px; ` +export const TripPannelTitle = styled.div` + display: flex; + justify-content: space-between; + align-items: center; +` + export const TripPanelHeading = styled(Panel.Heading)` background-color: white !important; + border-color: #fff !important; + padding: 20px 25px 0 25px; + + button { + background: transparent; + border: 0; + } + + h3 { + margin: 0; + } ` export const TripPanelAlert = styled.button` @@ -65,22 +82,7 @@ export const TripPanelAlert = styled.button` export const TripPanelFooter = styled(Panel.Footer)` background-color: white !important; padding: 0px; - button { - border: 0px; - padding: 13px 0px; - width: 50%; - } - - button:first-child { - border-top-left-radius: 0; - border-top-right-radius: 0; - border-bottom-right-radius: 0; - } - - button:nth-child(2) { - border-radius: 0; - border-left: 1px solid #ddd; - } + border: none; ` /** Formats non-