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
}
const { Component, CSSProperties, useEffect, useState, useCallback } = React;
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 }
]);
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();
}, []);
useEffect(() => {
const allHospitals = data.doctors.flatMap((doctor) => doctor.hospitals);
const uniqueHospitals = Array.from(
new Set(allHospitals.map((hospital) => hospital.id))
).map(
(hospitalId) =>
allHospitals.find((hospital) => hospital.id === hospitalId) as Hospital
);
setUniqueHospitals(uniqueHospitals);
if (uniqueHospitals.length > 0) {
setSelectedDoctorIdDiff([
{ type: "from", value: data.doctors[0].id },
{ type: "to", value: data.doctors[0].id }
]);
}
}, [data]);
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);
}, [
selectedDoctorIdDiff?.find((diff) => diff.type === "from")?.value,
selectedDoctorIdDiff?.find((diff) => diff.type === "to")?.value
]);
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
}
]);
},
[]
);
const divStyle: CSSProperties = {
display: "inline-block",
marginRight: ".5rem"
};
const spanStyle: CSSProperties = {
width: 20,
height: 20,
marginRight: ".5rem",
display: "inline-block",
verticalAlign: "middle"
};
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