438 lines
13 KiB
JavaScript
438 lines
13 KiB
JavaScript
import React, { Component } from "react";
|
||
import BeldenLogo from "../assets/images/belden-white.png";
|
||
import DefaultPartImg from "../assets/images/part.png";
|
||
import { NavLink } from "react-router-dom";
|
||
import Modal from "react-modal";
|
||
import "../assets/stylesheets/cabledetail.scss";
|
||
|
||
Modal.setAppElement("#root");
|
||
|
||
class Cable {
|
||
constructor(cableData) {
|
||
this.partnum = cableData.partnum;
|
||
this.id = cableData.id;
|
||
this.brand = cableData.brand;
|
||
this.position = cableData.position;
|
||
this.image = cableData.image
|
||
? `http://localhost${cableData.image}`
|
||
: DefaultPartImg;
|
||
this.dynamicProps = {};
|
||
this.horizontal = [];
|
||
this.vertical = [];
|
||
this.orderedKeys = [];
|
||
this.description = cableData.description;
|
||
this.short_description = cableData.short_description;
|
||
this.application = cableData.application;
|
||
this.category = cableData.category;
|
||
|
||
if (this.description === undefined) {
|
||
if (this.short_description !== undefined) {
|
||
this.description = this.short_description;
|
||
} else if (this.application !== undefined) {
|
||
this.description = this.application;
|
||
} else if (this.category !== undefined) {
|
||
this.description = this.category;
|
||
} else {
|
||
this.description = "";
|
||
}
|
||
}
|
||
|
||
if (this.description !== undefined) {
|
||
this.description =
|
||
this.description.charAt(0).toUpperCase() + this.description.slice(1);
|
||
if (this.description.length > 200) {
|
||
this.description = this.description.substring(0, 200) + "...";
|
||
}
|
||
}
|
||
|
||
Object.keys(cableData).forEach((key) => {
|
||
if (
|
||
![
|
||
"partnum",
|
||
"id",
|
||
"brand",
|
||
"position",
|
||
"image",
|
||
"short_description",
|
||
"description",
|
||
"application",
|
||
"category",
|
||
].includes(key)
|
||
) {
|
||
this.dynamicProps[key] = cableData[key];
|
||
}
|
||
});
|
||
|
||
for (let key in this.dynamicProps) {
|
||
let data = this.dynamicProps[key];
|
||
let first = Object.keys(data)[0];
|
||
if (typeof data[first] === "object") {
|
||
this.horizontal.push(key);
|
||
} else {
|
||
this.vertical.push(key);
|
||
}
|
||
}
|
||
this.orderedKeys = this.orderedKeys.concat(this.vertical);
|
||
this.orderedKeys = this.orderedKeys.concat(this.horizontal);
|
||
|
||
for (let i = 0; i < this.orderedKeys.length; i++) {
|
||
let key = this.orderedKeys[i];
|
||
if (!isNaN(key)) {
|
||
this.orderedKeys.splice(i, 1);
|
||
i--;
|
||
}
|
||
|
||
try {
|
||
let data = this.dynamicProps[key];
|
||
let first = Object.keys(data)[0];
|
||
if (data[first] !== undefined) {
|
||
if (typeof data[first] === "string") {
|
||
if (first === "" || data[first] === "") {
|
||
this.orderedKeys.splice(i, 1);
|
||
i--;
|
||
}
|
||
}
|
||
}
|
||
} catch (error) {}
|
||
}
|
||
}
|
||
}
|
||
|
||
export default class CableDetailComponent extends Component {
|
||
constructor(props) {
|
||
super(props);
|
||
this.state = {
|
||
cableDetails: null,
|
||
modalOpen_dispense: false,
|
||
modalOpen_show: false,
|
||
modalOpen_datasheet: false,
|
||
modalOpacity: 0,
|
||
};
|
||
this.openModal = this.openModal.bind(this);
|
||
this.closeModal = this.closeModal.bind(this);
|
||
}
|
||
|
||
openModal = (modal) => {
|
||
this.setState({ [modal]: true }, () => {
|
||
setTimeout(() => this.setState({ modalOpacity: 1 }), 10);
|
||
});
|
||
|
||
if (modal === "modalOpen_dispense") {
|
||
this.props.socket.send(
|
||
`{"type": "cable_get","call": "send","data": {"position": ${this.state.cableDetails.position}}}`
|
||
);
|
||
} else if (modal === "modalOpen_show") {
|
||
this.props.socket.send(
|
||
`{"type": "cable_get","call": "request","data": {"position": ${this.state.cableDetails.position}}}`
|
||
);
|
||
}
|
||
};
|
||
|
||
closeModal = (modal) => {
|
||
this.setState({ modalOpacity: 0 }, () => {
|
||
setTimeout(() => this.setState({ [modal]: false }), 300);
|
||
});
|
||
};
|
||
|
||
componentDidMount() {
|
||
const cablePos = window.location.href.split("/").pop();
|
||
this.props.socket.send(
|
||
`{"type":"cable_details","call":"request","data":{"position":["${cablePos}"]}}`
|
||
);
|
||
this.props.socket.addEventListener("message", this.handleMessage);
|
||
}
|
||
|
||
handleMessage = (event) => {
|
||
try {
|
||
console.log("Message from server", event.data);
|
||
const message = JSON.parse(event.data);
|
||
const cableDetails = new Cable(message.data.cables[0]);
|
||
this.setState({ cableDetails });
|
||
} catch (error) {
|
||
console.error("Error parsing message from server:", error);
|
||
}
|
||
};
|
||
|
||
componentWillUnmount() {
|
||
this.props.socket.removeEventListener("message", this.handleMessage);
|
||
}
|
||
|
||
renderHorizontalTable(title, object) {
|
||
let data;
|
||
try {
|
||
data = JSON.parse(object);
|
||
} catch (error) {
|
||
console.error("Error parsing JSON data:", error);
|
||
return <div>Error loading data...</div>;
|
||
}
|
||
|
||
const validKeys = Object.keys(data).filter((key) =>
|
||
Array.isArray(data[key])
|
||
);
|
||
|
||
const maxRows = Math.max(...validKeys.map((key) => data[key].length));
|
||
|
||
const rows = Array.from({ length: maxRows }).map((_, rowIndex) => {
|
||
return (
|
||
<tr className="row" key={rowIndex}>
|
||
{validKeys.map((key, index) => (
|
||
<td className="body" key={index}>
|
||
{data[key][rowIndex] || ""}
|
||
</td>
|
||
))}
|
||
</tr>
|
||
);
|
||
});
|
||
|
||
return (
|
||
<div className="cable-tables-div" style={{ width: "100%" }}>
|
||
<span className="cable-tables-div-title">{title}</span>
|
||
<table>
|
||
<thead className="thead">
|
||
<tr className="row">
|
||
{validKeys.map((key, index) => (
|
||
<th className="head" key={index}>
|
||
{key}
|
||
</th>
|
||
))}
|
||
</tr>
|
||
</thead>
|
||
<tbody className="tbody">{rows}</tbody>
|
||
</table>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
renderVerticalTable(title, object) {
|
||
let data;
|
||
try {
|
||
data = JSON.parse(object);
|
||
} catch (error) {
|
||
console.error("Error parsing JSON data:", error);
|
||
return <div>Error loading data...</div>;
|
||
}
|
||
|
||
return (
|
||
<div className="cable-tables-div">
|
||
<span className="cable-tables-div-title">{title}</span>
|
||
<table>
|
||
{Object.entries(data).map(([key, value], index) => (
|
||
<tr className="row" key={index}>
|
||
<th className="head">{key}</th>
|
||
<td className="body">{value}</td>
|
||
</tr>
|
||
))}
|
||
</table>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
render() {
|
||
const {
|
||
modalOpen_dispense,
|
||
modalOpen_show,
|
||
modalOpen_datasheet,
|
||
modalOpacity,
|
||
cableDetails,
|
||
} = this.state;
|
||
const modalStyle = {
|
||
content: {
|
||
opacity: modalOpacity,
|
||
transition: "opacity 300ms ease-in-out",
|
||
top: "50%",
|
||
left: "50%",
|
||
right: "auto",
|
||
bottom: "auto",
|
||
marginRight: "-50%",
|
||
width: "30%",
|
||
height: "30%",
|
||
transform: "translate(-50%, -50%)",
|
||
overflow: "hidden",
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
borderRadius: "20px",
|
||
background:
|
||
"linear-gradient(-30deg, rgb(187, 194, 236) 0%, rgba(255, 255, 255, 1) 100%)",
|
||
boxShadow: "0 0 20px rgba(0, 0, 0, 0.5)",
|
||
},
|
||
overlay: {
|
||
opacity: modalOpacity,
|
||
transition: "opacity 300ms ease-in-out",
|
||
backgroundColor: "rgba(255, 255, 255, 0.15)",
|
||
backdropFilter: "blur(5px)",
|
||
},
|
||
};
|
||
|
||
return (
|
||
<div className="cable">
|
||
<div className="cable-image">
|
||
<img src={BeldenLogo} alt="Belden" />
|
||
</div>
|
||
<div className="cable-fieldContainer">
|
||
<div className="cable-actions">
|
||
<NavLink to="/browse" className="cable-actions-back">
|
||
<span>⬅️ Back</span>
|
||
</NavLink>
|
||
</div>
|
||
{cableDetails ? (
|
||
<div className="cable-main">
|
||
<img
|
||
className="cable-main-image"
|
||
src={cableDetails.image}
|
||
alt="Cable"
|
||
/>
|
||
<div className="cable-main-label">
|
||
<div className="cable-main-name">{cableDetails.partnum}</div>
|
||
<div className="cable-main-description">
|
||
{cableDetails.description}
|
||
</div>
|
||
|
||
{cableDetails.category ? (
|
||
<div className="cable-main-category">
|
||
<span
|
||
style={{ color: "black", backgroundColor: "transparent" }}
|
||
>
|
||
Category:{" "}
|
||
</span>
|
||
{cableDetails.category}
|
||
</div>
|
||
) : null}
|
||
|
||
<div className="cable-main-brand">
|
||
<span
|
||
style={{ color: "black", backgroundColor: "transparent" }}
|
||
>
|
||
Brand:{" "}
|
||
</span>
|
||
{cableDetails.brand}
|
||
</div>
|
||
<div className="cable-main-position">
|
||
<span
|
||
style={{ color: "black", backgroundColor: "transparent" }}
|
||
>
|
||
Position:{" "}
|
||
</span>
|
||
{cableDetails.position}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
) : (
|
||
<div className="cable-main"></div>
|
||
)}
|
||
<div className="cable-actions">
|
||
<div
|
||
className="cable-actions-button"
|
||
onClick={() => this.openModal("modalOpen_datasheet")}
|
||
>
|
||
<span>➤ Datasheet</span>
|
||
<span>✏️</span>
|
||
</div>
|
||
<Modal
|
||
isOpen={modalOpen_datasheet}
|
||
onRequestClose={() => this.closeModal("modalOpen_datasheet")}
|
||
contentLabel="show"
|
||
style={modalStyle}
|
||
>
|
||
<div className="modal-container">
|
||
<div className="modal-title">
|
||
<span>✏️</span>
|
||
<span>Datasheet</span>
|
||
</div>
|
||
<div className="modal-body">
|
||
<span>Datasheet coming soon...</span>
|
||
</div>
|
||
<div
|
||
className="modal-close"
|
||
onClick={() => this.closeModal("modalOpen_datasheet")}
|
||
>
|
||
<span>Close</span>
|
||
</div>
|
||
</div>
|
||
</Modal>
|
||
<div
|
||
className="cable-actions-button"
|
||
onClick={() => this.openModal("modalOpen_show")}
|
||
>
|
||
<span>➤ Show</span>
|
||
<span>💡</span>
|
||
</div>
|
||
<Modal
|
||
isOpen={modalOpen_show}
|
||
onRequestClose={() => this.closeModal("modalOpen_show")}
|
||
contentLabel="show"
|
||
style={modalStyle}
|
||
>
|
||
<div className="modal-container">
|
||
<div className="modal-title">
|
||
<span>💡</span>
|
||
<span>Showing Item</span>
|
||
</div>
|
||
<div className="modal-body">
|
||
<span>The item will now be illuminated.</span>
|
||
</div>
|
||
<div
|
||
className="modal-close"
|
||
onClick={() => this.closeModal("modalOpen_show")}
|
||
>
|
||
<span>Close</span>
|
||
</div>
|
||
</div>
|
||
</Modal>
|
||
<div
|
||
className="cable-actions-button"
|
||
onClick={() => this.openModal("modalOpen_dispense")}
|
||
>
|
||
<span>➤ Dispense</span>
|
||
<span>🤖</span>
|
||
</div>
|
||
<Modal
|
||
isOpen={modalOpen_dispense}
|
||
onRequestClose={() => this.closeModal("modalOpen_dispense")}
|
||
contentLabel="Dispense"
|
||
style={modalStyle}
|
||
>
|
||
<div className="modal-container">
|
||
<div className="modal-title">
|
||
<span>🤖</span>
|
||
<span>Dispensing Item</span>
|
||
</div>
|
||
<div className="modal-body">
|
||
<span>Please wait for your item to be dispensed.</span>
|
||
</div>
|
||
<div
|
||
className="modal-close"
|
||
onClick={() => this.closeModal("modalOpen_dispense")}
|
||
>
|
||
<span>Close</span>
|
||
</div>
|
||
</div>
|
||
</Modal>
|
||
</div>
|
||
|
||
{cableDetails ? (
|
||
<div className="cable-tables">
|
||
{cableDetails.orderedKeys.map((key, index) => {
|
||
if (cableDetails.horizontal.includes(key)) {
|
||
return this.renderHorizontalTable(
|
||
key,
|
||
JSON.stringify(cableDetails.dynamicProps[key])
|
||
);
|
||
} else {
|
||
return this.renderVerticalTable(
|
||
key,
|
||
JSON.stringify(cableDetails.dynamicProps[key])
|
||
);
|
||
}
|
||
})}
|
||
</div>
|
||
) : (
|
||
<div className="cable-tables"></div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
}
|