Skip to content
Snippets Groups Projects
PlanElement.tsx 3.13 KiB
Newer Older
  • Learn to ignore specific revisions
  • import {motion} from 'framer-motion';
    import React, {useEffect, useState} from 'react';
    
    import ProgressIndicator from "./ProgressIndicator";
    
    import classNames from "../../../util/classNames";
    
    
    const PlanElement = (props: {
    
      trainIdentifier: string,
      trainHeading: string,
      stops: {
    
        name: string,
        arrival: Date,
    
        delay?: number,
        cancelled: boolean
    
      }[]
    }) => {
    
      const [shown, setShown] = useState<boolean>(true);
    
      useEffect(() => {
        const update = () => {
          const latestStop = props.stops.reduce((accu, curr) => {
            if (curr.arrival >= accu) {
              return curr.arrival;
            }
            return accu;
          }, new Date(0));
    
          if ((new Date()).getTime() <= latestStop.getTime()) {
            setShown(true);
          } else {
            setShown(false);
          }
        };
    
        update();
        const updateInterval = setInterval(update, 1000);
    
        return () => {
          clearInterval(updateInterval);
        }
    
        // eslint-disable-next-line react-hooks/exhaustive-deps
    
      return (
    
        <motion.div
          className={"overflow-hidden"}
          initial={{
    
            opacity: 1,
            translateY: "0%",
            marginTop: "0rem"
    
          }}
          animate={shown ? {
            opacity: 1,
    
            marginTop: "0rem"
          } : {
            opacity: 0,
    
            height: 0,
            marginTop: "-0.75rem"
          }}
          transition={{
            duration: .5,
            ease: "easeOut",
            staggerChildren: .3
          }}
        >
    
          <div className={"flex flex-row gap-4 items-center font-semibold"}>
    
            <div className={classNames(
              "flex justify-center items-center text-lg h-10 w-20 leading-none",
              trainIdentifierToColor(props.trainIdentifier)
            )}>
    
              {props.trainIdentifier}
            </div>
    
            <h3 className={"text-xl leading-9"}>
              {deDortmund(props.trainHeading)}
    
          <motion.ol role="list" className="overflow-hidden" aria-hidden="true">
            {
              props.stops.map((stop, index) => (
                <ProgressIndicator
    
                  key={stop.name}
    
                  first={index === 0}
                  id={stop.name}
    
                  arrival={stop.arrival}
    
                  cancelled={stop.cancelled}
    
          </motion.ol>
    
        </motion.div>
    
      );
    };
    
    export default PlanElement;
    
    
    
    const trainIdentifierToColor = (identifier: string): string => {
    
      if (identifier.startsWith("S")) {
    
      if (identifier.startsWith("X")) {
    
        return "bg-pink-700";
      }
    
      // Fixme: This should just be "if first is number"
    
      if (identifier.startsWith("4")) {
    
        return "bg-sky-700";
      }
    
      return "bg-zinc-700";
    }
    
    
    const deDortmund = (input: string): string => {
      // Don't remove the city from central station location
    
      if (input.includes("Hbf")) {
    
    
      return input
        // In all other cases, remove dortmund
        .replaceAll("Dortmund/Joseph Fraunhofer", "Joseph-von-Fraunhofer")
        // Special case: Because the API is dumb, translate JvF to be consistent
        .replaceAll("Dortmund ", "");