<div class="container"></div>
body {
  padding: 2rem 2rem 4rem;
}
ul {
    display: block;
    list-style-type: disc;
    margin-block-start: 1em;
    margin-block-end: 1em;
    margin-inline-start: 0px;
    margin-inline-end: 0px;
    padding-inline-start: 40px;
}
h2 {
  display: block;
    font-size: 1.17em;
    margin-block-start: 1em;
    margin-block-end: 1em;
    margin-inline-start: 0px;
    margin-inline-end: 0px;
    font-weight: bold;
}
h3 {
  display: block;
    font-size: 1em;
    margin-block-start: 1em;
    margin-block-end: 1em;
    margin-inline-start: 0px;
    margin-inline-end: 0px;
    font-weight: bold;
}
table {
    margin-top: 1rem;
    margin-bottom: 1rem;
}
table thead {
    background-color: #f2f2f2;
    text-align: left;
}

label {
    display: block;
    margin-right: 0.5rem;
}
select {
    border-radius: 2px;
    padding: 0.75rem 1rem;
    -moz-appearance: none;
    -webkit-appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    -ms-appearance: none;
    appearance: none;
  background: transparent;
  background-image: url("data:image/svg+xml;utf8,<svg fill='black' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path d='M7 10l5 5 5-5z'/><path d='M0 0h24v24H0z' fill='none'/></svg>");
  background-repeat: no-repeat;
  background-position-x: 98%;
  background-position-y: 12px;
  border: 1px solid #ccc; 
  width: 320px;
}
option {
  width: 100%;
    border-radius: 10px;
    padding: 1rem;
}
.box {
  margin: 0rem auto 3rem auto
}
//ES6 const, let
//ES6 Destructuring
const { Component, CSSProperties, useEffect, useState, useCallback } = React;

// TypeScript interfaces
interface Doctor {
  id: number;
  name: string;
  specialty: string;
  hospitals: {
    id: number;
    name: string;
    location: string;
  }[];
  experience: string;
  contact: string;
  email: string;
}

interface Hospital {
  id: number;
  name: string;
  location: string;

  diff?: CSSProperties;
}

const App = () => {
  const [data, setData] = useState<{ doctors: Doctor[] }>({ doctors: [] });
  const [uniqueHospitals, setUniqueHospitals] = useState<Hospital[]>([]);
  const [flatDiffHospitals, setFlatDiffHospitals] = useState<Hospital[]>([]);
  const [selectedDoctorIdDiff, setSelectedDoctorIdDiff] = useState<
    {
      type: "from" | "to" | "";
      value: number;
    }[]
  >([
    { type: "from", value: 0 },
    { type: "to", value: 0 }
  ]);

  // Get JSON data
  useEffect(() => {
    const getDoctors = async () =>
      await fetch(
        "https://raw.githubusercontent.com/dyarfi/doctors.json/master/doctorHospital.json"
      ).then(async (items) => {
        const itemsJson = await items.json();
        setData({ doctors: itemsJson.data });
      });
    getDoctors();
  }, []);

  // Set JSON data
  useEffect(() => {
    // Ensure unique hospitals
    const allHospitals = data.doctors.flatMap((doctor) => doctor.hospitals);

    // Populate the dropdown with unique hospital names
    const uniqueHospitals = Array.from(
      new Set(allHospitals.map((hospital) => hospital.id))
    ).map(
      (hospitalId) =>
        allHospitals.find((hospital) => hospital.id === hospitalId) as Hospital
    );
    // Initially set all hospitals
    setUniqueHospitals(uniqueHospitals);

    // Handle case when there are hospitals
    if (uniqueHospitals.length > 0) {
      setSelectedDoctorIdDiff([
        { type: "from", value: data.doctors[0].id },
        { type: "to", value: data.doctors[0].id }
      ]);
    }
  }, [data]);

  // effect for selected doctor dropdown changes
  useEffect(() => {
    const allHospitalsFrom = data?.doctors?.find(
      ({ id }) =>
        id === selectedDoctorIdDiff?.find((diff) => diff.type === "from")?.value
    );
    const allHospitalsTo = data?.doctors?.find(
      ({ id }) =>
        id === selectedDoctorIdDiff?.find((diff) => diff.type === "to")?.value
    );
    listAllDoctorHospitals(allHospitalsFrom as Doctor, allHospitalsTo as Doctor);

    /* deps from dropdown value changes taken from and to */
  }, [
    selectedDoctorIdDiff?.find((diff) => diff.type === "from")?.value,
    selectedDoctorIdDiff?.find((diff) => diff.type === "to")?.value
  ]);

  // Compare callbacks
  const listAllDoctorHospitals = useCallback(
    (dataFrom: Doctor, dataTo: Doctor) => {
      const renderContent = (id: number) => {
        const value = dataFrom?.hospitals?.filter((hospital) => hospital.id === id);
        const comparedValue = dataTo?.hospitals?.filter(
          (hospital) => hospital.id === id
        );

        if (!comparedValue) {
          return {};
        }
        if (value && Array.isArray(value)) {
          const isSame =
            value?.length == comparedValue?.length &&
            value?.every((element, index) => {
              return element?.id === comparedValue[index]?.id;
            });
          if (isSame) {
            return { fontWeight: 600, color: "#ff790a" };
          }
          return {};
        }
        return {};
      };

      setFlatDiffHospitals(
        dataFrom?.hospitals.map((hospital) => {
          return {
            ...hospital,
            diff: renderContent(hospital?.id)
          };
        })
      );
    },
    []
  );

  const handleDropdownChangeDiff = useCallback(
    (event: ChangeEvent<HTMLSelectElement>, type: "from" | "to") => {
      const id = parseInt(event.target.value);

      setSelectedDoctorIdDiff((prevState) => [
        ...prevState?.filter((item: any) => item?.type !== type),
        {
          type,
          value: id
        }
      ]);
    },
    []
  );

  // Styles
  const divStyle: CSSProperties = {
    display: "inline-block",
    marginRight: ".5rem"
  };

  const spanStyle: CSSProperties = {
    width: 20,
    height: 20,
    marginRight: ".5rem",
    display: "inline-block",
    verticalAlign: "middle"
  };

  // Render the component with the fetched data
  return (
    <div>
      <div className="box">
        <div style={{ display: "flex" }}>
          <div style={{ marginRight: "2rem" }}>
            <h3>Find Doctor Hospitals Comparison JSON From:</h3>
            <form>
              <label htmlFor="doctorDropdown">Select From Doctor:</label>
              <select
                id="doctorDropdownFrom"
                name="selectedDoctorIdDiffFrom"
                onChange={(e) => handleDropdownChangeDiff(e, "from")}
                value={
                  (selectedDoctorIdDiff.length &&
                    selectedDoctorIdDiff.find((doctor) => doctor.type == "from")
                      ?.value) ||
                  ""
                }
              >
                {data.doctors.map((doctor) => (
                  <option key={doctor.id} value={doctor.id}>
                    {doctor.name}
                  </option>
                ))}
              </select>
            </form>
          </div>

          <div style={{ marginRight: "2rem" }}>
            <h3>Find Doctor Hospitals Comparison JSON To:</h3>
            <form>
              <label htmlFor="doctorDropdown">Select To Doctor:</label>
              <select
                id="doctorDropdownTo"
                name="selectedDoctorIdDiffTo"
                onChange={(e) => handleDropdownChangeDiff(e, "to")}
                value={
                  (selectedDoctorIdDiff.length &&
                    selectedDoctorIdDiff.find((doctor) => doctor.type == "to")?.value) ||
                  ""
                }
              >
                {data.doctors.map((doctor) => (
                  <option key={doctor.id} value={doctor.id}>
                    {doctor.name}
                  </option>
                ))}
              </select>
            </form>
          </div>

          <div
            style={{
              marginRight: "2rem",
              alignSelf: "end"
            }}
          >
            Legends:
            <div>
              <div style={...divStyle}>
                <span style={{ ...spanStyle, background: "#ff790a" }}></span>
                <span>Same hospital</span>
              </div>
              <div style={...divStyle}>
                <span style={{ ...spanStyle, background: "#333333" }}></span>
                <span>Different hospital</span>
              </div>
            </div>
          </div>
        </div>

        <div>
          <table className="mantine-Table-table">
            <thead className="mantine-Table-thead">
              <tr className="mantine-Table-tr">
                <th>ID</th>
                <th>Name</th>
                <th>Location</th>
              </tr>
            </thead>
            <tbody className="mantine-Table-tbody">
              {flatDiffHospitals &&
                flatDiffHospitals.map((hospital) => (
                  <tr key={hospital.id} style={hospital?.diff}>
                    <td style={{ width: "10%" }}>{hospital.id}</td>
                    <td style={{ width: "20%" }}>{hospital.name}</td>
                    <td style={{ width: "20%" }}>{hospital.location}</td>
                  </tr>
                ))}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
};

ReactDOM.render(<App />, document.querySelector(".container"));
View Compiled

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js
  3. https://unpkg.com/@types/react@16.8.6/index.d.ts
  4. https://unpkg.com/@types/react-dom@16.8.6/index.d.ts
  5. https://unpkg.com/@types/react-dom@16.8.4/index.d.ts