import { Image, Text, View } from "react-native"; import { icons } from "@/constants"; import { tr } from "@/lib/i18n"; import { formatDate, formatTime } from "@/lib/utils"; import type { Ride } from "@/types/type"; // How a finished ride ended. The history list used to render every ride // identically โ€” a cancelled trip showed the same driver, the same fare and, on // a card ride, the same green "Paid by card" as one that actually happened, so // a rider scrolling their history saw cancellations as completed journeys. // The outcome is now the first thing on the card. const OUTCOME = { completed: { labelKey: "components.rideCard.outcomeCompleted", text: "text-emerald-600 dark:text-emerald-400", chip: "bg-emerald-500/10", }, cancelled: { labelKey: "components.rideCard.outcomeCancelled", text: "text-rose-500", chip: "bg-rose-500/10", }, expired: { labelKey: "components.rideCard.outcomeExpired", text: "text-amber-600 dark:text-amber-400", chip: "bg-amber-500/10", }, } as const; export const RideCard = ({ ride }: { ride: Ride }) => { const { destination_latitude, destination_longitude, origin_address, destination_address, created_at, ride_time, driver, payment_status, status, cancelled_by, cancellation_reason, } = ride; const outcome = OUTCOME[status as keyof typeof OUTCOME] ?? null; const didNotHappen = status === "cancelled" || status === "expired"; // A cancelled or expired ride never had a driver assigned in most cases, and // the LEFT JOIN hands back an object of nulls โ€” which rendered as an empty // gap where a name should be. const driverName = [driver?.first_name, driver?.last_name] .filter(Boolean) .join(" "); return ( {outcome ? ( {tr(outcome.labelKey)} {/* Who ended it, and why โ€” the two things a rider looking back at a cancelled trip actually wants to know. */} {didNotHappen && cancelled_by ? ( {cancelled_by === "system" ? tr("components.rideCard.cancelledBySystem") : tr( cancelled_by === "driver" ? "components.rideCard.cancelledByDriver" : "components.rideCard.cancelledByYou", )} {cancellation_reason ? ` ยท ${tr(`cancelSheet.reasons.${cancellation_reason}`)}` : ""} ) : null} ) : null} {tr("components.rideCard.mapAlt")} {tr("components.rideCard.originAlt")} {origin_address} {tr("components.rideCard.destinationAlt")} {destination_address} {tr("components.rideCard.dateTime")} {formatDate(created_at)}, {formatTime(ride_time)} {tr("components.rideCard.driver")} {driverName || tr("components.rideCard.noDriver")} {tr("components.rideCard.carSeats")} {driver.car_seats} {tr("components.rideCard.fare")} ${(ride.fare_price / 100).toFixed(2)} {tr("components.rideCard.paymentStatus")} {/* A ride that never happened has no payment worth reporting as successful. A cash ride simply wasn't collected; a card ride that was charged before cancellation is called out as owed a refund rather than shown as a cheerful green "Paid". */} {didNotHappen ? payment_status === "paid" ? tr("components.rideCard.paymentRefundDue") : tr("components.rideCard.paymentNotCharged") : payment_status === "cash" ? tr("components.rideCard.paymentCash") : payment_status === "cash_collected" ? tr("components.rideCard.paymentCashCollected") : payment_status === "paid" ? tr("components.rideCard.paymentPaid") : tr("components.rideCard.paymentOther", { status: payment_status, })} ); };