documentation equipment
parent
fdae12fc88
commit
5116def685
|
@ -15,7 +15,8 @@ import { useContext } from "react";
|
||||||
import GroupTasks from "../../Pages/GroupTasks/Overview";
|
import GroupTasks from "../../Pages/GroupTasks/Overview";
|
||||||
import GroupTasksHistory from "../../Pages/GroupTasks/History";
|
import GroupTasksHistory from "../../Pages/GroupTasks/History";
|
||||||
import PageNotFound from "../../Pages/PageNotFound";
|
import PageNotFound from "../../Pages/PageNotFound";
|
||||||
import EquipmentDocumentation from "../../Pages/EquipmentDocumentation";
|
import EquipmentDocumentationOverview from "../../Pages/EquipmentDocumentation";
|
||||||
|
import ViewEquipmentDocumentations from "../../Pages/EquipmentDocumentation/ViewEquipmentDocumentation";
|
||||||
|
|
||||||
export default function AppRoutes() {
|
export default function AppRoutes() {
|
||||||
const webSocketContext = useContext(WebSocketContext);
|
const webSocketContext = useContext(WebSocketContext);
|
||||||
|
@ -48,15 +49,14 @@ export default function AppRoutes() {
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION}
|
path={Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION}
|
||||||
element={<EquipmentDocumentation isEquipmentCreateModalOpen={false} />}
|
element={<EquipmentDocumentationOverview />}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={
|
path={
|
||||||
Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION_CREATE +
|
Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION + "/:paramStockItemId"
|
||||||
":paramStockItemId"
|
|
||||||
}
|
}
|
||||||
element={<EquipmentDocumentation isEquipmentCreateModalOpen={true} />}
|
element={<ViewEquipmentDocumentations />}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { Spin } from "antd";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function MyImage({ src, width, style }) {
|
||||||
|
const [loaded, setLoaded] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{loaded ? null : (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
height: 200,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Spin />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<img
|
||||||
|
src={src}
|
||||||
|
width={width}
|
||||||
|
style={loaded ? style : { display: "none" }}
|
||||||
|
alt="Image"
|
||||||
|
onLoad={() => setLoaded(true)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -117,13 +117,23 @@ export function MyModalCloseSaveButtonFooter({ onCancel, onSave }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MyModalCloseCreateButtonFooter({ onCancel, onCreate }) {
|
export function MyModalCloseCreateButtonFooter({
|
||||||
|
onCancel,
|
||||||
|
onCreate,
|
||||||
|
isCreateButtonDisabled,
|
||||||
|
isCreateButtonLoading,
|
||||||
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button onClick={onCancel}>{t("common.button.close")}</Button>
|
<Button onClick={onCancel}>{t("common.button.close")}</Button>
|
||||||
<Button onClick={onCreate} type="primary">
|
<Button
|
||||||
|
onClick={onCreate}
|
||||||
|
type="primary"
|
||||||
|
disabled={isCreateButtonDisabled}
|
||||||
|
loading={isCreateButtonLoading}
|
||||||
|
>
|
||||||
{t("common.button.create")}
|
{t("common.button.create")}
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import MyModal, {
|
import MyModal, {
|
||||||
MyModalCloseCreateButtonFooter,
|
MyModalCloseCreateButtonFooter,
|
||||||
MyModalCloseSaveButtonFooter,
|
|
||||||
} from "../../Components/MyModal";
|
} from "../../Components/MyModal";
|
||||||
import { AppStyle, Constants, myFetch, myFetchContentType } from "../../utils";
|
import { AppStyle, Constants, myFetch } from "../../utils";
|
||||||
import { Button, Card, Col, Row, Select, Typography } from "antd";
|
import { Button, Card, Col, Row, Select, Typography } from "antd";
|
||||||
import { createRef, useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
import TextArea from "antd/es/input/TextArea";
|
import TextArea from "antd/es/input/TextArea";
|
||||||
import Webcam from "react-webcam";
|
import Webcam from "react-webcam";
|
||||||
import {
|
import {
|
||||||
|
@ -14,20 +13,17 @@ import {
|
||||||
FullscreenOutlined,
|
FullscreenOutlined,
|
||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { DocumentationImage } from ".";
|
import MyImage from "../../Components/MyImage";
|
||||||
|
|
||||||
function UploadComponent({ index, setImagePreview }) {
|
function UploadComponent({ index, setImagePreview }) {
|
||||||
const handleFileChange = (event) => {
|
const handleFileChange = (event) => {
|
||||||
const file = event.target.files[0];
|
const file = event.target.files[0];
|
||||||
console.log("file", event.target.files);
|
|
||||||
if (file) {
|
if (file) {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onload = () => {
|
reader.onload = () => {
|
||||||
//setImagePreview(URL.createObjectURL(file));
|
//setImagePreview(URL.createObjectURL(file));
|
||||||
setImagePreview(reader.result);
|
setImagePreview(reader.result);
|
||||||
|
|
||||||
// base 64 string
|
|
||||||
// console.log(reader.result);
|
|
||||||
};
|
};
|
||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
}
|
}
|
||||||
|
@ -116,49 +112,101 @@ export function NoteComponent({
|
||||||
description,
|
description,
|
||||||
onDescriptionChange,
|
onDescriptionChange,
|
||||||
onDeleteImage,
|
onDeleteImage,
|
||||||
|
imageDocumentationId,
|
||||||
}) {
|
}) {
|
||||||
return (
|
const [isImageFullScreenModalOpen, setIsImageFullScreenModalOpen] =
|
||||||
<Row
|
useState(false);
|
||||||
gutter={AppStyle.grid.row.glutter}
|
|
||||||
style={{ marginBottom: AppStyle.app.marginBottom }}
|
|
||||||
>
|
|
||||||
<Col xs={24} md={8}>
|
|
||||||
<Card
|
|
||||||
bodyStyle={{ padding: 0 }}
|
|
||||||
actions={
|
|
||||||
viewMode
|
|
||||||
? [<FullscreenOutlined />]
|
|
||||||
: [
|
|
||||||
<UploadComponent
|
|
||||||
index={index}
|
|
||||||
setImagePreview={onImageChange}
|
|
||||||
/>,
|
|
||||||
<CameraComponent setImagePreview={onImageChange} />,
|
|
||||||
<DeleteOutlined onClick={onDeleteImage} />,
|
|
||||||
<FullscreenOutlined />,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<DocumentationImage
|
|
||||||
image={image}
|
|
||||||
imgStyle={{ borderTopLeftRadius: 6, borderTopRightRadius: 6 }}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
<Col xs={24} md={16}>
|
const imageSrc = imageDocumentationId
|
||||||
{viewMode ? (
|
? `${Constants.STATIC_CONTENT_ADDRESS}equipmentdocumentation/${imageDocumentationId}/${image}`
|
||||||
<Typography.Text>{description}</Typography.Text>
|
: image;
|
||||||
) : (
|
|
||||||
<TextArea
|
const FullscreenOutlinedIcon = ({ disabled }) => (
|
||||||
rows={8}
|
<FullscreenOutlined
|
||||||
placeholder="Description"
|
disabled={true}
|
||||||
value={description}
|
onClick={() => {
|
||||||
onChange={onDescriptionChange}
|
if (disabled) return;
|
||||||
/>
|
|
||||||
)}
|
setIsImageFullScreenModalOpen(true);
|
||||||
</Col>
|
}}
|
||||||
</Row>
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ marginBottom: AppStyle.app.margin }}>
|
||||||
|
<Row gutter={[AppStyle.grid.row.gutter[0]]}>
|
||||||
|
<Col xs={24} md={8}>
|
||||||
|
<Card
|
||||||
|
bodyStyle={{ padding: 0 }}
|
||||||
|
actions={
|
||||||
|
viewMode
|
||||||
|
? image
|
||||||
|
? [<FullscreenOutlinedIcon />]
|
||||||
|
: null
|
||||||
|
: [
|
||||||
|
<UploadComponent
|
||||||
|
index={index}
|
||||||
|
setImagePreview={onImageChange}
|
||||||
|
/>,
|
||||||
|
<CameraComponent setImagePreview={onImageChange} />,
|
||||||
|
<DeleteOutlined onClick={onDeleteImage} />,
|
||||||
|
<FullscreenOutlinedIcon disabled={image === null} />,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{!image ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
height: 250,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{viewMode ? "No image" : "No image selected"}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<MyImage
|
||||||
|
src={imageSrc}
|
||||||
|
width="100%"
|
||||||
|
style={{
|
||||||
|
borderTopLeftRadius: 6,
|
||||||
|
borderTopRightRadius: 6,
|
||||||
|
}}
|
||||||
|
alt="Preview"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
<Col xs={24} md={16}>
|
||||||
|
{viewMode ? (
|
||||||
|
<Typography.Text>{description}</Typography.Text>
|
||||||
|
) : (
|
||||||
|
<TextArea
|
||||||
|
rows={8}
|
||||||
|
placeholder="Description"
|
||||||
|
value={description}
|
||||||
|
onChange={onDescriptionChange}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<ImageFullscreenModal
|
||||||
|
isOpen={isImageFullScreenModalOpen}
|
||||||
|
onCancel={() => setIsImageFullScreenModalOpen(false)}
|
||||||
|
image={imageSrc}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ImageFullscreenModal({ isOpen, onCancel, image }) {
|
||||||
|
return (
|
||||||
|
<MyModal isOpen={isOpen} onCancel={onCancel}>
|
||||||
|
<img width="100%" src={image} alt="Fullscreen preview" />
|
||||||
|
</MyModal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,30 +217,52 @@ const selectDocumentationTypeOptions = [
|
||||||
{ value: 1, label: "Documentation" },
|
{ value: 1, label: "Documentation" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function CreateEquipmentDocumentationModal({ isOpen }) {
|
export default function CreateEquipmentDocumentationModal({
|
||||||
const navigate = useNavigate();
|
fetchDocumentation,
|
||||||
|
buttonBlock,
|
||||||
|
}) {
|
||||||
let { paramStockItemId } = useParams();
|
let { paramStockItemId } = useParams();
|
||||||
|
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [title, setTitle] = useState("New documentation");
|
const [title, setTitle] = useState("New documentation");
|
||||||
const [selectedDocumentationType, setSelectedDocumentationType] = useState(
|
const [selectedDocumentationType, setSelectedDocumentationType] = useState(
|
||||||
selectDocumentationTypeOptions[0].value
|
selectDocumentationTypeOptions[0].value
|
||||||
);
|
);
|
||||||
const [notes, setNotes] = useState([emptyNote]);
|
const [notes, setNotes] = useState([emptyNote]);
|
||||||
|
const [isDocumentationUploading, setIsDocumentationUploading] =
|
||||||
|
useState(false);
|
||||||
|
|
||||||
const handleCancel = () =>
|
const handleCancel = () => setIsOpen(false);
|
||||||
navigate(Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION);
|
|
||||||
|
|
||||||
const handleCreate = () => {
|
const handleCreate = () => {
|
||||||
let obj = {
|
setIsDocumentationUploading(true);
|
||||||
|
|
||||||
|
const updatedNotes = [...notes];
|
||||||
|
|
||||||
|
updatedNotes.forEach((note, index) => {
|
||||||
|
if (note.image === null && note.description === "") {
|
||||||
|
updatedNotes.splice(index, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let body = {
|
||||||
stockItemId: paramStockItemId,
|
stockItemId: paramStockItemId,
|
||||||
type: selectedDocumentationType,
|
type: selectedDocumentationType,
|
||||||
title: title,
|
title: title,
|
||||||
notes: notes,
|
notes: updatedNotes,
|
||||||
};
|
};
|
||||||
|
|
||||||
myFetch(`/equipment/documentation/create`, "POST", obj, {}).then((data) => {
|
console.log("body", body);
|
||||||
console.log("data", data);
|
|
||||||
});
|
myFetch(`/equipment/documentation/create`, "POST", body, {}).then(
|
||||||
|
(data) => {
|
||||||
|
console.log("data", data);
|
||||||
|
|
||||||
|
setIsDocumentationUploading(false);
|
||||||
|
fetchDocumentation();
|
||||||
|
handleCancel();
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDescriptionChange = (index) => (e) => {
|
const handleDescriptionChange = (index) => (e) => {
|
||||||
|
@ -225,57 +295,83 @@ export default function CreateEquipmentDocumentationModal({ isOpen }) {
|
||||||
return lastNote.image === null && lastNote.description === "";
|
return lastNote.image === null && lastNote.description === "";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isCreateButtonDisabled = () => {
|
||||||
|
if (notes.length === 0) return true;
|
||||||
|
|
||||||
|
if (notes.length === 1) {
|
||||||
|
return notes[0].image === null && notes[0].description === "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MyModal
|
<>
|
||||||
isOpen={isOpen}
|
<Button
|
||||||
onCancel={handleCancel}
|
block={buttonBlock}
|
||||||
footer={
|
type="primary"
|
||||||
<MyModalCloseCreateButtonFooter
|
icon={<PlusOutlined />}
|
||||||
onCreate={handleCreate}
|
onClick={() => setIsOpen(true)}
|
||||||
onCancel={handleCancel}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Typography.Title
|
|
||||||
editable={{ text: title, onChange: setTitle }}
|
|
||||||
level={1}
|
|
||||||
>
|
>
|
||||||
{title}
|
Create documentation
|
||||||
</Typography.Title>
|
</Button>
|
||||||
|
|
||||||
<div style={{ marginBottom: AppStyle.typography.text.marginBottom }}>
|
<MyModal
|
||||||
<Typography.Text>Documentation type</Typography.Text>
|
isOpen={isOpen}
|
||||||
</div>
|
onCancel={handleCancel}
|
||||||
|
footer={
|
||||||
<Select
|
<MyModalCloseCreateButtonFooter
|
||||||
defaultValue={selectedDocumentationType}
|
onCreate={handleCreate}
|
||||||
style={{ width: "100%", marginBottom: AppStyle.app.marginBottom }}
|
isCreateButtonDisabled={isCreateButtonDisabled()}
|
||||||
onChange={(value) => setSelectedDocumentationType(value)}
|
isCreateButtonLoading={isDocumentationUploading}
|
||||||
options={selectDocumentationTypeOptions}
|
onCancel={handleCancel}
|
||||||
/>
|
/>
|
||||||
|
}
|
||||||
{notes.map((note, index) => (
|
>
|
||||||
<NoteComponent
|
<Typography.Title
|
||||||
key={index}
|
editable={{ text: title, onChange: setTitle }}
|
||||||
index={index}
|
level={1}
|
||||||
image={note.image}
|
|
||||||
onImageChange={handleImageChange(index)}
|
|
||||||
description={note.description}
|
|
||||||
onDescriptionChange={handleDescriptionChange(index)}
|
|
||||||
onDeleteImage={() => handleImageChange(index)(null)}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
|
|
||||||
<div style={{ textAlign: "center" }}>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
disabled={isAddNoteButtonDisabled()}
|
|
||||||
icon={<PlusOutlined />}
|
|
||||||
onClick={handleAddNote}
|
|
||||||
>
|
>
|
||||||
Add note
|
{title}
|
||||||
</Button>
|
</Typography.Title>
|
||||||
</div>
|
|
||||||
</MyModal>
|
<div style={{ marginBottom: AppStyle.typography.text.marginBottom }}>
|
||||||
|
<Typography.Text>Documentation type</Typography.Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
defaultValue={selectedDocumentationType}
|
||||||
|
style={{ width: "100%", marginBottom: AppStyle.app.margin }}
|
||||||
|
onChange={(value) => setSelectedDocumentationType(value)}
|
||||||
|
options={selectDocumentationTypeOptions}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{notes.map((note, index) => (
|
||||||
|
<NoteComponent
|
||||||
|
key={index}
|
||||||
|
index={index}
|
||||||
|
image={note.image}
|
||||||
|
onImageChange={handleImageChange(index)}
|
||||||
|
description={note.description}
|
||||||
|
onDescriptionChange={handleDescriptionChange(index)}
|
||||||
|
onDeleteImage={() => handleImageChange(index)(null)}
|
||||||
|
onImageFullscreen={() => {
|
||||||
|
console.log("onImageFullscreen");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<div style={{ textAlign: "center" }}>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
disabled={isAddNoteButtonDisabled()}
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={handleAddNote}
|
||||||
|
>
|
||||||
|
Add note
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</MyModal>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
import { Constants } from "../../utils";
|
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
|
||||||
import { MyLazyLoadingModal } from "../../Components/MyModal";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { Steps } from "antd";
|
|
||||||
import MyAttachments from "../../Components/MyAttachments";
|
|
||||||
|
|
||||||
export default function EquipmentViewModal({ isOpen }) {
|
|
||||||
//const { t } = useTranslation();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
let { paramEquipmentId } = useParams();
|
|
||||||
|
|
||||||
const [equipment, setEquipment] = useState([]);
|
|
||||||
|
|
||||||
const handleCancel = () =>
|
|
||||||
navigate(Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION);
|
|
||||||
|
|
||||||
console.log("equipment", equipment);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<MyLazyLoadingModal
|
|
||||||
isOpen={isOpen}
|
|
||||||
onCancel={handleCancel}
|
|
||||||
resultTitleNoDataFound={"Not found"}
|
|
||||||
setFoundData={setEquipment}
|
|
||||||
fetchUrl={`/equipment/documentation/${paramEquipmentId}`}
|
|
||||||
fetchType={"GET"}
|
|
||||||
>
|
|
||||||
<h1>This is my children</h1>
|
|
||||||
|
|
||||||
<Steps
|
|
||||||
direction="vertical"
|
|
||||||
current={1}
|
|
||||||
items={[
|
|
||||||
{
|
|
||||||
title: "Finished",
|
|
||||||
description: (
|
|
||||||
<>
|
|
||||||
<p style={{ color: "#000" }}>
|
|
||||||
<b>Started at:</b> 18.8.2023, 00:59:10
|
|
||||||
<br />
|
|
||||||
<b>Endet at:</b> 18.8.2023, 00:59:13
|
|
||||||
<br />
|
|
||||||
<b>Duration:</b> 3s 516ms
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<MyAttachments
|
|
||||||
attachments={[
|
|
||||||
{
|
|
||||||
OriginalFileName: "test.png",
|
|
||||||
SystemFileName:
|
|
||||||
"e74fc0c4-4114-4d48-8ca2-5adb77d98ebe.jpg",
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
downloadUrl={`${Constants.STATIC_CONTENT_ADDRESS}grouptasks/df1fc270-485c-4d9a-8439-dc7fbc151f4c/`}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "In Progress",
|
|
||||||
description: "This is a description.",
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</MyLazyLoadingModal>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -0,0 +1,295 @@
|
||||||
|
import {
|
||||||
|
Breadcrumb,
|
||||||
|
Button,
|
||||||
|
Card,
|
||||||
|
Col,
|
||||||
|
Popover,
|
||||||
|
Result,
|
||||||
|
Row,
|
||||||
|
Spin,
|
||||||
|
Typography,
|
||||||
|
} from "antd";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||||
|
import MyImage from "../../Components/MyImage";
|
||||||
|
import CreateEquipmentDocumentationModal, {
|
||||||
|
NoteComponent,
|
||||||
|
} from "./CreateEquipmentDocumentationModal";
|
||||||
|
import { AppStyle, Constants, FormatDatetime, myFetch } from "../../utils";
|
||||||
|
import {
|
||||||
|
BookOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
InfoCircleOutlined,
|
||||||
|
ToolOutlined,
|
||||||
|
} from "@ant-design/icons";
|
||||||
|
|
||||||
|
export default function ViewEquipmentDocumentations() {
|
||||||
|
let { paramStockItemId } = useParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const [equipmentDocumentationResponse, setEquipmentDocumentationResponse] =
|
||||||
|
useState(null);
|
||||||
|
const [isEquipmentDocumentationLoading, setIsEquipmentDocumentationLoading] =
|
||||||
|
useState(false);
|
||||||
|
|
||||||
|
const fetchDocumentation = () => {
|
||||||
|
setIsEquipmentDocumentationLoading(true);
|
||||||
|
|
||||||
|
myFetch(`/equipment/documentation/${paramStockItemId}`, "GET").then(
|
||||||
|
(data) => {
|
||||||
|
console.log("data", data);
|
||||||
|
|
||||||
|
const updatedData = { ...data };
|
||||||
|
|
||||||
|
// sort by date
|
||||||
|
// last created will be on top of the list
|
||||||
|
updatedData.Documentations = data.Documentations.sort(
|
||||||
|
(a, b) => new Date(b.CreatedAt) - new Date(a.CreatedAt)
|
||||||
|
);
|
||||||
|
|
||||||
|
setIsEquipmentDocumentationLoading(false);
|
||||||
|
setEquipmentDocumentationResponse(updatedData);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("paramStockItemId", paramStockItemId);
|
||||||
|
|
||||||
|
fetchDocumentation();
|
||||||
|
}, [paramStockItemId]);
|
||||||
|
|
||||||
|
const CreateDocumentationButton = () => {
|
||||||
|
return (
|
||||||
|
<Row style={{ alignItems: "center" }}>
|
||||||
|
<Col xs={24} sm={{ span: 8 }} md={{ span: 6 }}>
|
||||||
|
<MyImage
|
||||||
|
src={
|
||||||
|
"http://localhost:50050/v1/equipment/thumbnail/media/part_images/part_153_image.thumbnail.png"
|
||||||
|
}
|
||||||
|
width={64}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
<Col xs={24} sm={{ span: 8, offset: 8 }} md={{ span: 6, offset: 12 }}>
|
||||||
|
<CreateEquipmentDocumentationModal
|
||||||
|
fetchDocumentation={fetchDocumentation}
|
||||||
|
buttonBlock={true}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const DocumentationContent = ({ documentation }) => {
|
||||||
|
return (
|
||||||
|
<Card style={{ marginTop: AppStyle.app.margin }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: 10,
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginBottom: AppStyle.typography.text.marginBottom,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: 10,
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DocumentationTypeIcon type={documentation.Type} />
|
||||||
|
<Typography.Title level={4} style={{ margin: 0 }}>
|
||||||
|
{documentation.Title}
|
||||||
|
</Typography.Title>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: 10,
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Popover
|
||||||
|
title={
|
||||||
|
<Typography.Title
|
||||||
|
level={4}
|
||||||
|
style={{ color: Constants.COLORS.SECONDARY }}
|
||||||
|
>
|
||||||
|
Details
|
||||||
|
</Typography.Title>
|
||||||
|
}
|
||||||
|
trigger="click"
|
||||||
|
placement="left"
|
||||||
|
content={
|
||||||
|
<p style={{ color: "#000", margin: 0 }}>
|
||||||
|
<b>ID:</b> {documentation.Id}
|
||||||
|
<br />
|
||||||
|
<b>Type:</b> {documentation.Type}
|
||||||
|
<br />
|
||||||
|
<b>Created at:</b> {FormatDatetime(documentation.CreatedAt)}
|
||||||
|
<br />
|
||||||
|
<b>Updated at:</b> {FormatDatetime(documentation.UpdatedAt)}
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<InfoCircleOutlined
|
||||||
|
style={{ fontSize: 24, color: Constants.COLORS.ICON_INFO }}
|
||||||
|
onClick={() => console.log("info")}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
|
||||||
|
<EditOutlined
|
||||||
|
style={{ fontSize: 24 }}
|
||||||
|
onClick={() => console.log("edit")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{documentation.Notes !== "" &&
|
||||||
|
JSON.parse(documentation.Notes).map((note, index) => {
|
||||||
|
console.log("map doc");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NoteComponent
|
||||||
|
key={index}
|
||||||
|
viewMode
|
||||||
|
image={note.Image}
|
||||||
|
imageDocumentationId={documentation.Id}
|
||||||
|
description={note.Description}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isEquipmentDocumentationLoading) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
marginTop: 120,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Spin size="large" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (equipmentDocumentationResponse === null) return null;
|
||||||
|
|
||||||
|
// backend unauthorized to access invex
|
||||||
|
if (equipmentDocumentationResponse.Status === 401) {
|
||||||
|
return (
|
||||||
|
<Result
|
||||||
|
status="403"
|
||||||
|
title="401"
|
||||||
|
subTitle="The backend server is not authorized to access invex."
|
||||||
|
extra={
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
onClick={() =>
|
||||||
|
navigate(Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Back to Overview
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// stock item doesn't exists on invex
|
||||||
|
if (equipmentDocumentationResponse.Status === 404) {
|
||||||
|
return (
|
||||||
|
<Result
|
||||||
|
status="500"
|
||||||
|
title="500"
|
||||||
|
subTitle="The scanned item doesn't exists on invex"
|
||||||
|
extra={
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
onClick={() =>
|
||||||
|
navigate(Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Back to Overview
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (equipmentDocumentationResponse.Documentations.length === 0) {
|
||||||
|
return (
|
||||||
|
<Result
|
||||||
|
status="404"
|
||||||
|
title="404"
|
||||||
|
subTitle="Sorry, for the equipment does not exist an documentation."
|
||||||
|
extra={[
|
||||||
|
<Button
|
||||||
|
key="0"
|
||||||
|
onClick={() =>
|
||||||
|
navigate(Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Back to Overview
|
||||||
|
</Button>,
|
||||||
|
<CreateEquipmentDocumentationModal
|
||||||
|
key="1"
|
||||||
|
fetchDocumentation={fetchDocumentation}
|
||||||
|
buttonBlock={false}
|
||||||
|
/>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Breadcrumb
|
||||||
|
style={{ marginBottom: AppStyle.app.margin }}
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
title: (
|
||||||
|
<Link to={Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION}>
|
||||||
|
Overview
|
||||||
|
</Link>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{ title: `Stock Item ${paramStockItemId}` },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CreateDocumentationButton />
|
||||||
|
|
||||||
|
{equipmentDocumentationResponse.Documentations.map(
|
||||||
|
(documentation, index) => (
|
||||||
|
<DocumentationContent key={index} documentation={documentation} />
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function DocumentationTypeIcon({ type }) {
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
return <ToolOutlined style={{ fontSize: 24 }} />;
|
||||||
|
case 1:
|
||||||
|
return <BookOutlined style={{ fontSize: 24 }} />;
|
||||||
|
default:
|
||||||
|
console.log("DocumentationTypeIcon type not found:", type);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,185 +1,207 @@
|
||||||
import { CameraOutlined } from "@ant-design/icons";
|
import { CameraOutlined, SearchOutlined } from "@ant-design/icons";
|
||||||
import { Button, Card, Col, Input, Result, Row, Typography } from "antd";
|
import { Button, Card, Col, Input, Result, Row, Typography } from "antd";
|
||||||
import { AppStyle, Constants, myFetch } from "../../utils";
|
import { AppStyle, Constants } from "../../utils";
|
||||||
import { useEffect, useState } from "react";
|
import { useState } from "react";
|
||||||
import { QrScanner } from "@yudiel/react-qr-scanner";
|
import { QrScanner } from "@yudiel/react-qr-scanner";
|
||||||
import EquipmentViewModal from "./EquipmentViewModal";
|
import { useNavigate } from "react-router-dom";
|
||||||
import CreateEquipmentDocumentationModal, {
|
|
||||||
NoteComponent,
|
export default function EquipmentDocumentationOverview() {
|
||||||
} from "./CreateEquipmentDocumentationModal";
|
return (
|
||||||
import { Link } from "react-router-dom";
|
<>
|
||||||
|
<ScanEquipmentComponent />
|
||||||
|
|
||||||
|
<Result
|
||||||
|
status="404"
|
||||||
|
title="No equipment scanned"
|
||||||
|
subTitle="Scan a equipment to see the documentation."
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
function DocumentationTypeIcon({ type }) {
|
||||||
|
switch (type) {
|
||||||
|
case 0:
|
||||||
|
return <ToolOutlined style={{ fontSize: 24 }} />;
|
||||||
|
case 1:
|
||||||
|
return <BookOutlined style={{ fontSize: 24 }} />;
|
||||||
|
default:
|
||||||
|
console.log("DocumentationTypeIcon type not found:", type);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
/*
|
||||||
|
export function EquipmentDocumentation() {
|
||||||
|
let { paramStockItemId } = useParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
export default function EquipmentDocumentation({ isEquipmentCreateModalOpen }) {
|
|
||||||
const [isScannerActive, setIsScannerActive] = useState(false);
|
|
||||||
// const [fetchingEquipment, setFetchingEquipment] = useState(false);
|
|
||||||
const [scannerResult, setScannerResult] = useState("");
|
|
||||||
const [equipmentDocumentation, setEquipmentDocumentation] = useState([]);
|
const [equipmentDocumentation, setEquipmentDocumentation] = useState([]);
|
||||||
|
const [isEquipmentDocumentationLoading, setIsEquipmentDocumentationLoading] =
|
||||||
|
useState(false);
|
||||||
|
const [isEquipmentCreateModalOpen, setIsEquipmentCreateModalOpen] =
|
||||||
|
useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
const scannerResult = paramStockItemId;
|
||||||
console.log("scannerResult", scannerResult);
|
|
||||||
|
|
||||||
if (scannerResult === "") return;
|
const setScannerResult = (v) => {
|
||||||
|
console.log("set scanne result", v);
|
||||||
|
navigate(`${Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION}/${v}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchDocumentation = () => {
|
||||||
|
if (!scannerResult) return;
|
||||||
|
|
||||||
|
setIsEquipmentDocumentationLoading(true);
|
||||||
|
|
||||||
myFetch(`/equipment/documentation/${scannerResult}`, "GET").then((data) => {
|
myFetch(`/equipment/documentation/${scannerResult}`, "GET").then((data) => {
|
||||||
console.log("data", data);
|
console.log("data", data);
|
||||||
|
|
||||||
setEquipmentDocumentation(data);
|
// sort by date
|
||||||
|
// last created will be on top of the list
|
||||||
|
const sortedData = data.sort(
|
||||||
|
(a, b) => new Date(b.CreatedAt) - new Date(a.CreatedAt)
|
||||||
|
);
|
||||||
|
|
||||||
//setEquipment(data);
|
setIsEquipmentDocumentationLoading(false);
|
||||||
//setFetchingEquipment(false);
|
setEquipmentDocumentation(sortedData);
|
||||||
});
|
});
|
||||||
}, [scannerResult]);
|
|
||||||
|
|
||||||
// const [equipment, setEquipment] = useState([]);
|
|
||||||
|
|
||||||
/*useEffect(() => {
|
|
||||||
console.log("eq");
|
|
||||||
|
|
||||||
setFetchingEquipment(true);
|
|
||||||
|
|
||||||
myFetch("/equipment", "GET").then((data) => {
|
|
||||||
setEquipment(data);
|
|
||||||
setFetchingEquipment(false);
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const getTableColumns = () => {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
title: "Name",
|
|
||||||
dataIndex: "name",
|
|
||||||
key: "name",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Last modification",
|
|
||||||
dataIndex: "lastModification",
|
|
||||||
key: "lastModification",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Last modified at",
|
|
||||||
dataIndex: "lastModifiedAt",
|
|
||||||
key: "lastModifiedAt",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Action",
|
|
||||||
dataIndex: "action",
|
|
||||||
key: "action",
|
|
||||||
render: (_, record) => {
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
to={
|
|
||||||
Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION_VIEW + record.key
|
|
||||||
}
|
|
||||||
>
|
|
||||||
View
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTableItems = () => {
|
useEffect(() => {
|
||||||
return equipment.map((eq) => ({
|
console.log("scannerResult", scannerResult);
|
||||||
key: eq.Id,
|
|
||||||
name: (
|
|
||||||
<>
|
|
||||||
<Popover
|
|
||||||
placement="right"
|
|
||||||
trigger="hover"
|
|
||||||
content={
|
|
||||||
<Avatar
|
|
||||||
src={`${Constants.API_ADDRESS}/equipment/thumbnail${eq.Thumbnail}`}
|
|
||||||
size={256}
|
|
||||||
shape="square"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<>
|
|
||||||
<Avatar
|
|
||||||
src={`${Constants.API_ADDRESS}/equipment/thumbnail${eq.Thumbnail}`}
|
|
||||||
shape="square"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
</Popover>
|
|
||||||
|
|
||||||
{eq.Name}
|
fetchDocumentation();
|
||||||
</>
|
}, [scannerResult]);
|
||||||
),
|
|
||||||
}));
|
|
||||||
}; */
|
|
||||||
|
|
||||||
const CreateDocumentationButton = () => {
|
const CreateDocumentationButton = () => {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Row style={{ alignItems: "center" }}>
|
||||||
to={`${Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION_CREATE}${scannerResult}`}
|
<Col xs={24} sm={{ span: 8 }} md={{ span: 6 }}>
|
||||||
>
|
<MyImage
|
||||||
<Button type="primary">Create documentation</Button>
|
src={
|
||||||
</Link>
|
"http://localhost:50050/v1/equipment/thumbnail/media/part_images/part_153_image.thumbnail.png"
|
||||||
|
}
|
||||||
|
width={64}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
<Col xs={24} sm={{ span: 8, offset: 8 }} md={{ span: 6, offset: 12 }}>
|
||||||
|
<CreateEquipmentDocumentationModal />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const DocumentationContent = ({ documentation }) => {
|
const DocumentationContent = ({ documentation }) => {
|
||||||
console.log("doc", documentation);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card style={{ marginTop: AppStyle.app.margin }}>
|
||||||
<Typography.Title level={4}>{documentation.Title}</Typography.Title>
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: 10,
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginBottom: AppStyle.typography.text.marginBottom,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: 10,
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DocumentationTypeIcon type={documentation.Type} />
|
||||||
|
<Typography.Title level={4} style={{ margin: 0 }}>
|
||||||
|
{documentation.Title}
|
||||||
|
</Typography.Title>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: 10,
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Popover
|
||||||
|
title={
|
||||||
|
<Typography.Title
|
||||||
|
level={4}
|
||||||
|
style={{ color: Constants.COLORS.SECONDARY }}
|
||||||
|
>
|
||||||
|
Details
|
||||||
|
</Typography.Title>
|
||||||
|
}
|
||||||
|
trigger="click"
|
||||||
|
placement="left"
|
||||||
|
content={
|
||||||
|
<p style={{ color: "#000", margin: 0 }}>
|
||||||
|
<b>ID:</b> {documentation.Id}
|
||||||
|
<br />
|
||||||
|
<b>Type:</b> {documentation.Type}
|
||||||
|
<br />
|
||||||
|
<b>Created at:</b> {FormatDatetime(documentation.CreatedAt)}
|
||||||
|
<br />
|
||||||
|
<b>Updated at:</b> {FormatDatetime(documentation.UpdatedAt)}
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<InfoCircleOutlined
|
||||||
|
style={{ fontSize: 24, color: Constants.COLORS.ICON_INFO }}
|
||||||
|
onClick={() => console.log("info")}
|
||||||
|
/>
|
||||||
|
</Popover>
|
||||||
|
|
||||||
|
<EditOutlined
|
||||||
|
style={{ fontSize: 24 }}
|
||||||
|
onClick={() => console.log("edit")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{documentation.Notes !== "" &&
|
{documentation.Notes !== "" &&
|
||||||
JSON.parse(documentation.Notes).map((note, index) => (
|
JSON.parse(documentation.Notes).map((note, index) => {
|
||||||
<NoteComponent
|
console.log("map doc");
|
||||||
key={index}
|
|
||||||
viewMode
|
return (
|
||||||
image={`${Constants.STATIC_CONTENT_ADDRESS}equipmentdocumentation/${documentation.Id}/${note.Image}`}
|
<NoteComponent
|
||||||
description={note.Description}
|
key={index}
|
||||||
/>
|
viewMode
|
||||||
))}
|
image={note.Image}
|
||||||
|
imageDocumentationId={documentation.Id}
|
||||||
|
description={note.Description}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Row style={{ marginBottom: AppStyle.app.marginBottom }}>
|
{isEquipmentDocumentationLoading ? (
|
||||||
<Col xs={0} sm={7} />
|
<div
|
||||||
<Col xs={24} sm={10}>
|
style={{
|
||||||
<Card
|
display: "flex",
|
||||||
style={{
|
alignItems: "center",
|
||||||
textAlign: "center",
|
justifyContent: "center",
|
||||||
}}
|
marginTop: 120,
|
||||||
>
|
}}
|
||||||
{isScannerActive ? (
|
>
|
||||||
<>
|
<Spin size="large" />
|
||||||
<QrScanner
|
</div>
|
||||||
onDecode={(result) => {
|
) : scannerResult === undefined ? (
|
||||||
console.log(result);
|
<Result
|
||||||
setScannerResult(result);
|
status="404"
|
||||||
setIsScannerActive(false);
|
title="No equipment scanned"
|
||||||
}}
|
subTitle="Scan a equipment to see the documentation."
|
||||||
onError={(error) => console.log(error?.message)}
|
/>
|
||||||
/>
|
) : scannerResult !== undefined && equipmentDocumentation.length === 0 ? (
|
||||||
<Button onClick={() => setIsScannerActive(false)}>
|
|
||||||
Close camera
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<div onClick={() => setIsScannerActive(true)}>
|
|
||||||
<CameraOutlined style={{ fontSize: 64 }} />
|
|
||||||
<Typography.Title level={5}>Scan equipment</Typography.Title>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
Result: {scannerResult}
|
|
||||||
<Input placeholder="Equipment id" />
|
|
||||||
<Button onClick={() => setScannerResult("169")}>Search</Button>
|
|
||||||
</Card>
|
|
||||||
</Col>
|
|
||||||
<Col xs={0} sm={7} />
|
|
||||||
</Row>
|
|
||||||
|
|
||||||
<h1>ScannerResult: {scannerResult}</h1>
|
|
||||||
|
|
||||||
{scannerResult !== "" && equipmentDocumentation.length === 0 ? (
|
|
||||||
<Result
|
<Result
|
||||||
status="404"
|
status="404"
|
||||||
title="404"
|
title="404"
|
||||||
|
@ -204,32 +226,80 @@ export default function EquipmentDocumentation({ isEquipmentCreateModalOpen }) {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<CreateEquipmentDocumentationModal isOpen={isEquipmentCreateModalOpen} />
|
<CreateEquipmentDocumentationModal
|
||||||
|
isOpen={isEquipmentCreateModalOpen}
|
||||||
|
onCancel={() => setIsEquipmentCreateModalOpen(false)}
|
||||||
|
fetchDocumentation={() => fetchDocumentation()}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
} */
|
||||||
|
|
||||||
export function DocumentationImage({ image, imgStyle }) {
|
export function ScanEquipmentComponent() {
|
||||||
return image ? (
|
const navigate = useNavigate();
|
||||||
<img
|
|
||||||
src={image}
|
const [isScannerActive, setIsScannerActive] = useState(false);
|
||||||
style={{
|
|
||||||
width: "100%",
|
const setScannerResult = (v) => {
|
||||||
...imgStyle,
|
console.log("set scanne result", v);
|
||||||
}}
|
navigate(`${Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION}/${v}`);
|
||||||
alt="Preview"
|
};
|
||||||
/>
|
|
||||||
) : (
|
return (
|
||||||
<div
|
<Row style={{ marginBottom: AppStyle.app.margin }}>
|
||||||
style={{
|
<Col xs={0} sm={7} />
|
||||||
height: 250,
|
<Col xs={24} sm={10}>
|
||||||
display: "flex",
|
<Card
|
||||||
justifyContent: "center",
|
style={{
|
||||||
alignItems: "center",
|
textAlign: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
No image selected
|
{isScannerActive ? (
|
||||||
</div>
|
<>
|
||||||
|
<QrScanner
|
||||||
|
onDecode={(result) => {
|
||||||
|
console.log(result);
|
||||||
|
setScannerResult(result);
|
||||||
|
setIsScannerActive(false);
|
||||||
|
}}
|
||||||
|
onError={(error) => console.log(error?.message)}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
block
|
||||||
|
onClick={() => setIsScannerActive(false)}
|
||||||
|
style={{
|
||||||
|
marginTop: AppStyle.app.margin,
|
||||||
|
marginBottom: AppStyle.app.margin,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Close camera
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div onClick={() => setIsScannerActive(true)}>
|
||||||
|
<CameraOutlined style={{ fontSize: 64 }} />
|
||||||
|
<Typography.Title level={5}>Scan equipment</Typography.Title>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Row gutter={AppStyle.grid.row.gutter}>
|
||||||
|
<Col xs={24} md={16}>
|
||||||
|
<Input placeholder="Equipment id" />
|
||||||
|
</Col>
|
||||||
|
<Col xs={24} md={8}>
|
||||||
|
<Button
|
||||||
|
block
|
||||||
|
icon={<SearchOutlined />}
|
||||||
|
onClick={() => setScannerResult("169")}
|
||||||
|
>
|
||||||
|
Search
|
||||||
|
</Button>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
<Col xs={0} sm={7} />
|
||||||
|
</Row>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ export const Constants = {
|
||||||
|
|
||||||
export const AppStyle = {
|
export const AppStyle = {
|
||||||
app: {
|
app: {
|
||||||
marginBottom: 12,
|
margin: 12,
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
},
|
},
|
||||||
typography: {
|
typography: {
|
||||||
|
@ -137,7 +137,7 @@ export const AppStyle = {
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
row: {
|
row: {
|
||||||
glutter: [16, 16],
|
gutter: [16, 16],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue