diff --git a/src/Components/AppRoutes/index.js b/src/Components/AppRoutes/index.js index eb65edf..c6259f6 100644 --- a/src/Components/AppRoutes/index.js +++ b/src/Components/AppRoutes/index.js @@ -41,6 +41,15 @@ export default function AppRoutes() { } element={} /> + + + + } + /> */ return ( @@ -52,13 +61,6 @@ export default function AppRoutes() { element={} /> - } - /> - } diff --git a/src/Components/MyModal/index.js b/src/Components/MyModal/index.js index 966f147..d96427b 100644 --- a/src/Components/MyModal/index.js +++ b/src/Components/MyModal/index.js @@ -104,13 +104,17 @@ export function MyModalOnlyCloseButtonFooter({ onCancel }) { return {t("common.button.close")}; } -export function MyModalCloseSaveButtonFooter({ onCancel, onSave }) { +export function MyModalCloseSaveButtonFooter({ + onCancel, + onSave, + isSaveButtonLoading, +}) { const { t } = useTranslation(); return ( <> {t("common.button.close")} - + {t("common.button.save")} > diff --git a/src/Pages/EquipmentDocumentation/CreateEquipmentDocumentationModal.js b/src/Pages/EquipmentDocumentation/CreateEquipmentDocumentationModal.js index 1868544..195db7b 100644 --- a/src/Pages/EquipmentDocumentation/CreateEquipmentDocumentationModal.js +++ b/src/Pages/EquipmentDocumentation/CreateEquipmentDocumentationModal.js @@ -1,228 +1,43 @@ -import { useParams } from "react-router-dom"; -import MyModal, { - MyModalCloseCreateButtonFooter, -} from "../../Components/MyModal"; -import { AppStyle, Constants, myFetch } from "../../utils"; -import { Button, Card, Col, Row, Select, Typography } from "antd"; -import { useRef, useState } from "react"; -import TextArea from "antd/es/input/TextArea"; -import Webcam from "react-webcam"; -import { - CameraOutlined, - DeleteOutlined, - FullscreenOutlined, - PlusOutlined, -} from "@ant-design/icons"; -import MyImage from "../../Components/MyImage"; +import { Button } from "antd"; +import { useState } from "react"; +import { PlusOutlined } from "@ant-design/icons"; +import { EquipmentDocumentationViewEditComponent } from "."; -function UploadComponent({ index, setImagePreview }) { - const handleFileChange = (event) => { - const file = event.target.files[0]; - - if (file) { - const reader = new FileReader(); - reader.onload = () => { - //setImagePreview(URL.createObjectURL(file)); - setImagePreview(reader.result); - }; - reader.readAsDataURL(file); - } - }; - - return ( - - - - - - - ); -} - -function CameraComponent({ setImagePreview }) { - const [modalVisible, setModalVisible] = useState(false); - const [cameraVisible, setCameraVisible] = useState(false); - const webcamRef = useRef(null); - - const handleCapture = () => { - const imageSrc = webcamRef.current.getScreenshot(); - setImagePreview(imageSrc); - - handleCancel(); - }; - - const handleCancel = () => { - setCameraVisible(false); - // this is needed to close the camera correctly - setTimeout(() => setModalVisible(false), 100); - }; +export default function CreateEquipmentDocumentationModal({ + stockItemId, + fetchDocumentation, + buttonBlock, +}) { + const [isOpen, setIsOpen] = useState(false); return ( <> - { - setModalVisible(true); - setCameraVisible(true); - }} + } + onClick={() => setIsOpen(true)} > - - + Create documentation + - - Take picture - , - ]} - > - {cameraVisible && ( - - )} - + setIsOpen(false)} + stockItemId={stockItemId} + fetchDocumentation={fetchDocumentation} + /> > ); } -export function NoteComponent({ - viewMode, - index, - image, - onImageChange, - description, - onDescriptionChange, - onDeleteImage, - imageDocumentationId, -}) { - const [isImageFullScreenModalOpen, setIsImageFullScreenModalOpen] = - useState(false); - - const imageSrc = imageDocumentationId - ? `${Constants.STATIC_CONTENT_ADDRESS}equipmentdocumentation/${imageDocumentationId}/${image}` - : image; - - const FullscreenOutlinedIcon = ({ disabled }) => ( - { - if (disabled) return; - - setIsImageFullScreenModalOpen(true); - }} - /> - ); - - return ( - - - - ] - : null - : [ - , - , - , - , - ] - } - > - {!image ? ( - - {viewMode ? "No image" : "No image selected"} - - ) : ( - - )} - - - - - {viewMode ? ( - {description} - ) : ( - - )} - - - - setIsImageFullScreenModalOpen(false)} - image={imageSrc} - /> - - ); -} - -function ImageFullscreenModal({ isOpen, onCancel, image }) { - return ( - - - - ); -} - -const emptyNote = { image: null, description: "" }; - -const selectDocumentationTypeOptions = [ - { value: 0, label: "Repair protocol" }, - { value: 1, label: "Documentation" }, -]; - +/* export default function CreateEquipmentDocumentationModal({ + scannerResult, fetchDocumentation, buttonBlock, }) { - let { paramStockItemId } = useParams(); - const [isOpen, setIsOpen] = useState(false); const [title, setTitle] = useState("New documentation"); const [selectedDocumentationType, setSelectedDocumentationType] = useState( @@ -246,7 +61,7 @@ export default function CreateEquipmentDocumentationModal({ }); let body = { - stockItemId: paramStockItemId, + stockItemId: scannerResult, type: selectedDocumentationType, title: title, notes: updatedNotes, @@ -340,7 +155,8 @@ export default function CreateEquipmentDocumentationModal({ setSelectedDocumentationType(value)} options={selectDocumentationTypeOptions} @@ -355,9 +171,6 @@ export default function CreateEquipmentDocumentationModal({ description={note.description} onDescriptionChange={handleDescriptionChange(index)} onDeleteImage={() => handleImageChange(index)(null)} - onImageFullscreen={() => { - console.log("onImageFullscreen"); - }} /> ))} @@ -375,3 +188,4 @@ export default function CreateEquipmentDocumentationModal({ > ); } +*/ diff --git a/src/Pages/EquipmentDocumentation/EditEquipmentDocumentationModal.js b/src/Pages/EquipmentDocumentation/EditEquipmentDocumentationModal.js new file mode 100644 index 0000000..9b8e0bc --- /dev/null +++ b/src/Pages/EquipmentDocumentation/EditEquipmentDocumentationModal.js @@ -0,0 +1,26 @@ +import { EditOutlined } from "@ant-design/icons"; +import { useState } from "react"; +import { EquipmentDocumentationViewEditComponent } from "."; + +export default function EditEquipmentDocumentationModal({ + stockItemId, + documentationId, + fetchDocumentation, +}) { + const [isOpen, setIsOpen] = useState(false); + + return ( + <> + setIsOpen(true)} /> + + setIsOpen(false)} + stockItemId={stockItemId} + documentationId={documentationId} + fetchDocumentation={fetchDocumentation} + /> + > + ); +} diff --git a/src/Pages/EquipmentDocumentation/ViewEquipmentDocumentation.js b/src/Pages/EquipmentDocumentation/ViewEquipmentDocumentation.js index 005012e..7df5fb5 100644 --- a/src/Pages/EquipmentDocumentation/ViewEquipmentDocumentation.js +++ b/src/Pages/EquipmentDocumentation/ViewEquipmentDocumentation.js @@ -1,5 +1,4 @@ import { - Breadcrumb, Button, Card, Col, @@ -10,23 +9,18 @@ import { 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 { useNavigate } from "react-router-dom"; +import CreateEquipmentDocumentationModal from "./CreateEquipmentDocumentationModal"; import { AppStyle, Constants, FormatDatetime, myFetch } from "../../utils"; import { BookOutlined, - EditOutlined, InfoCircleOutlined, ToolOutlined, } from "@ant-design/icons"; +import EditEquipmentDocumentationModal from "./EditEquipmentDocumentationModal"; +import { NoteComponent } from "."; -export default function ViewEquipmentDocumentations() { - let { paramStockItemId } = useParams(); - const navigate = useNavigate(); - +export default function ViewEquipmentDocumentations({ scannerResult }) { const [equipmentDocumentationResponse, setEquipmentDocumentationResponse] = useState(null); const [isEquipmentDocumentationLoading, setIsEquipmentDocumentationLoading] = @@ -35,7 +29,7 @@ export default function ViewEquipmentDocumentations() { const fetchDocumentation = () => { setIsEquipmentDocumentationLoading(true); - myFetch(`/equipment/documentation/${paramStockItemId}`, "GET").then( + myFetch(`/equipment/documentations/${scannerResult}`, "GET").then( (data) => { console.log("data", data); @@ -54,25 +48,55 @@ export default function ViewEquipmentDocumentations() { }; useEffect(() => { - console.log("paramStockItemId", paramStockItemId); + console.log("scannerResult", scannerResult); fetchDocumentation(); - }, [paramStockItemId]); + }, [scannerResult]); const CreateDocumentationButton = () => { + const InvexStockItemThumbnail = ({ width }) => { + return ( + + ); + }; + return ( - - + + {equipmentDocumentationResponse.Documentations.length !== 0 && ( + } + > + <> + + > + + )} + + + {scannerResult} + @@ -144,9 +168,10 @@ export default function ViewEquipmentDocumentations() { /> - console.log("edit")} + @@ -160,7 +185,7 @@ export default function ViewEquipmentDocumentations() { key={index} viewMode image={note.Image} - imageDocumentationId={documentation.Id} + documentationId={documentation.Id} description={note.Description} /> ); @@ -193,17 +218,6 @@ export default function ViewEquipmentDocumentations() { status="403" title="401" subTitle="The backend server is not authorized to access invex." - extra={ - <> - - navigate(Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION) - } - > - Back to Overview - - > - } /> ); } @@ -215,17 +229,6 @@ export default function ViewEquipmentDocumentations() { status="500" title="500" subTitle="The scanned item doesn't exists on invex" - extra={ - <> - - navigate(Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION) - } - > - Back to Overview - - > - } /> ); } @@ -237,16 +240,9 @@ export default function ViewEquipmentDocumentations() { title="404" subTitle="Sorry, for the equipment does not exist an documentation." extra={[ - - navigate(Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION) - } - > - Back to Overview - , , @@ -257,20 +253,6 @@ export default function ViewEquipmentDocumentations() { return ( <> - - Overview - - ), - }, - { title: `Stock Item ${paramStockItemId}` }, - ]} - /> - {equipmentDocumentationResponse.Documentations.map( @@ -284,9 +266,9 @@ export default function ViewEquipmentDocumentations() { function DocumentationTypeIcon({ type }) { switch (type) { - case 0: - return ; case 1: + return ; + case 2: return ; default: console.log("DocumentationTypeIcon type not found:", type); diff --git a/src/Pages/EquipmentDocumentation/index.js b/src/Pages/EquipmentDocumentation/index.js index e760127..eb41da5 100644 --- a/src/Pages/EquipmentDocumentation/index.js +++ b/src/Pages/EquipmentDocumentation/index.js @@ -1,313 +1,691 @@ -import { CameraOutlined, SearchOutlined } from "@ant-design/icons"; -import { Button, Card, Col, Input, Result, Row, Typography } from "antd"; -import { AppStyle, Constants } from "../../utils"; -import { useState } from "react"; +import { + ArrowDownOutlined, + ArrowUpOutlined, + CameraOutlined, + DeleteOutlined, + EllipsisOutlined, + FullscreenOutlined, + PlusOutlined, + SearchOutlined, +} from "@ant-design/icons"; +import { + Button, + Card, + Col, + Divider, + Dropdown, + Input, + Result, + Row, + Select, + Space, + Typography, + Upload, + message, +} from "antd"; +import { AppStyle, Constants, myFetch } from "../../utils"; +import { useEffect, useRef, useState } from "react"; import { QrScanner } from "@yudiel/react-qr-scanner"; -import { useNavigate } from "react-router-dom"; +import ViewEquipmentDocumentations from "./ViewEquipmentDocumentation"; +import MyModal, { + MyModalCloseCreateButtonFooter, + MyModalCloseSaveButtonFooter, +} from "../../Components/MyModal"; +import Webcam from "react-webcam"; +import TextArea from "antd/es/input/TextArea"; + +message.config({ + maxCount: 2, +}); export default function EquipmentDocumentationOverview() { + const [scannerResult, setScannerResult] = useState(""); + const [isScannerActive, setIsScannerActive] = useState(false); + const [inputValue, setInputValue] = useState(""); + + console.log("scan", scannerResult); + + const isScannedQrCodeValid = (result) => { + // {"stockitem": 11} or 11 is valid + + try { + // Try to parse the scanned content as JSON + const parsedResult = JSON.parse(result); + + // Check if the parsed object has the expected format + if (parsedResult && typeof parsedResult === "object") { + if ( + parsedResult.stockitem !== undefined && + typeof parsedResult.stockitem === "number" + ) { + return true; // The QR code has the expected format + } + } else if (!isNaN(parsedResult)) { + return true; // The QR code is a valid number + } + + return false; // The QR code does not have the expected format or value + } catch (error) { + return false; // Error while parsing the QR code + } + }; + return ( <> - - - - > - ); -} - -/* -function DocumentationTypeIcon({ type }) { - switch (type) { - case 0: - return ; - case 1: - return ; - default: - console.log("DocumentationTypeIcon type not found:", type); - return null; - } -} */ - -/* -export function EquipmentDocumentation() { - let { paramStockItemId } = useParams(); - const navigate = useNavigate(); - - const [equipmentDocumentation, setEquipmentDocumentation] = useState([]); - const [isEquipmentDocumentationLoading, setIsEquipmentDocumentationLoading] = - useState(false); - const [isEquipmentCreateModalOpen, setIsEquipmentCreateModalOpen] = - useState(false); - - const scannerResult = paramStockItemId; - - 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) => { - console.log("data", 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) - ); - - setIsEquipmentDocumentationLoading(false); - setEquipmentDocumentation(sortedData); - }); - }; - - useEffect(() => { - console.log("scannerResult", scannerResult); - - fetchDocumentation(); - }, [scannerResult]); - - const CreateDocumentationButton = () => { - return ( - - - - - - - - - - ); - }; - - const DocumentationContent = ({ documentation }) => { - return ( - - - + + + - - - {documentation.Title} - - + {isScannerActive ? ( + <> + { + console.log(result); - - console.log(error?.message)} + /> + setIsScannerActive(false)} + style={{ + marginTop: AppStyle.app.margin, + marginBottom: AppStyle.app.margin, + }} > - Details - - } - trigger="click" - placement="left" - content={ - - ID: {documentation.Id} - - Type: {documentation.Type} - - Created at: {FormatDatetime(documentation.CreatedAt)} - - Updated at: {FormatDatetime(documentation.UpdatedAt)} - - } - > - console.log("info")} - /> - + Close camera + + > + ) : ( + setIsScannerActive(true)}> + + Scan equipment + + )} - console.log("edit")} - /> - - + + + setInputValue(e.target.value)} + /> + + + } + onClick={() => { + if (!isScannedQrCodeValid(inputValue)) { + message.error("Invalid stock item code"); + return; + } - {documentation.Notes !== "" && - JSON.parse(documentation.Notes).map((note, index) => { - console.log("map doc"); + setScannerResult(inputValue); + }} + > + Search + + + + + + + - return ( - - ); - })} - - ); - }; - - return ( - <> - {isEquipmentDocumentationLoading ? ( - - - - ) : scannerResult === undefined ? ( + {scannerResult === "" ? ( - ) : scannerResult !== undefined && equipmentDocumentation.length === 0 ? ( - - setScannerResult("")}> - Back to Overview - - - - > - } - /> ) : ( - <> - - - {equipmentDocumentation.map((documentation, index) => ( - - ))} - > + )} - - setIsEquipmentCreateModalOpen(false)} - fetchDocumentation={() => fetchDocumentation()} - /> > ); -} */ - -export function ScanEquipmentComponent() { - const navigate = useNavigate(); - - const [isScannerActive, setIsScannerActive] = useState(false); - - const setScannerResult = (v) => { - console.log("set scanne result", v); - navigate(`${Constants.ROUTE_PATHS.EQUIPMENT_DOCUMENTATION}/${v}`); - }; - - return ( - - - - - {isScannerActive ? ( - <> - { - console.log(result); - setScannerResult(result); - setIsScannerActive(false); - }} - onError={(error) => console.log(error?.message)} - /> - setIsScannerActive(false)} - style={{ - marginTop: AppStyle.app.margin, - marginBottom: AppStyle.app.margin, - }} - > - Close camera - - > - ) : ( - setIsScannerActive(true)}> - - Scan equipment - - )} - - - - - - - } - onClick={() => setScannerResult("169")} - > - Search - - - - - - - - ); } -/* - { + setIsDocumentationUploading(true); + + const updatedNotes = [...notes]; + + updatedNotes.forEach((note, index) => { + if (note.Image === null && note.Description === "") { + updatedNotes.splice(index, 1); + } + }); + + let body = { + stockItemId: stockItemId, + type: selectedDocumentationType, + title: title, + notes: updatedNotes, + }; + + console.log("body", body); + + myFetch(`/equipment/documentation/create`, "POST", body, {}).then( + (data) => { + console.log("data", data); + + setIsDocumentationUploading(false); + fetchDocumentation(); + onCancel(); + } + ); + }; + + const handleEdit = () => { + setIsDocumentationUploading(true); + + const updatedNotes = [...notes]; + + console.log("documentationResponse.current", documentationResponse.current); + + updatedNotes.forEach((note, index) => { + if (note.Image?.startsWith("http")) { + updatedNotes[index].Image = JSON.parse( + documentationResponse.current.Notes + )[index].Image; + } + }); + + let body = { + documentationId: documentationId, + type: selectedDocumentationType, + title: title, + notes: updatedNotes, + }; + + console.log("body", body); + + myFetch(`/equipment/documentation/edit`, "POST", body, {}).then((data) => { + console.log("data", data); + + setIsDocumentationUploading(false); + fetchDocumentation(); + onCancel(); + }); + }; + + const handleDescriptionChange = (index) => (e) => { + const updatedNotes = [...notes]; + + updatedNotes[index] = { + ...updatedNotes[index], + Description: e.target.value, + }; + + setNotes(updatedNotes); + }; + + const handleImageChange = (index) => (newImage) => { + const updatedNotes = [...notes]; + + updatedNotes[index] = { + ...updatedNotes[index], + Image: newImage, + }; + + setNotes(updatedNotes); + }; + + const handleAddNote = () => setNotes([...notes, EmptyNote]); + + const isAddNoteButtonDisabled = () => { + const lastNote = notes[notes.length - 1]; + + 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; + }; + + // triggers on edit documentation + useEffect(() => { + if (!isOpen) return; + if (createMode) return; + + myFetch( + `/equipment/documentation/${stockItemId}/${documentationId}`, + "GET" + ).then((data) => { + console.log("data", data); + + documentationResponse.current = data; + + setTitle(data.Title); + + // adding the static server url in front of the file name + const updatedDataNotes = JSON.parse(data.Notes); + + updatedDataNotes.forEach((note, index) => { + if (note.Image !== "") { + updatedDataNotes[ + index + ].Image = `${Constants.STATIC_CONTENT_ADDRESS}equipmentdocumentation/${documentationId}/${note.Image}`; + } + }); + + setNotes(updatedDataNotes); + setSelectedDocumentationType(data.Type); + }); + }, [isOpen]); + + return ( + + ) : ( + + ) + } + > + + {title} + + + + Documentation type + + + setSelectedDocumentationType(value)} + options={selectDocumentationTypeOptions} /> -*/ + + {notes.map((note, index) => ( + handleImageChange(index)(null)} + documentationId={documentationId} + onMoveUp={() => { + if (index === 0) return; + + // updating the notes + const updatedNotes = [...notes]; + const temp = updatedNotes[index - 1]; + updatedNotes[index - 1] = updatedNotes[index]; + updatedNotes[index] = temp; + + setNotes(updatedNotes); + + if (createMode) return; + + // updating the documentationResponse.current + const updatedCurrentNotes = JSON.parse( + documentationResponse.current.Notes + ); + + const temp2 = updatedCurrentNotes[index - 1]; + updatedCurrentNotes[index - 1] = updatedCurrentNotes[index]; + updatedCurrentNotes[index] = temp2; + + documentationResponse.current = { + ...documentationResponse.current, + Notes: JSON.stringify(updatedCurrentNotes), + }; + }} + onMoveDown={() => { + if (index === notes.length - 1) return; + + // updating the notes + const updatedNotes = [...notes]; + const temp = updatedNotes[index + 1]; + updatedNotes[index + 1] = updatedNotes[index]; + updatedNotes[index] = temp; + + setNotes(updatedNotes); + + if (createMode) return; + + // updating the documentationResponse.current + const updatedCurrentNotes = JSON.parse( + documentationResponse.current.Notes + ); + + const temp2 = updatedCurrentNotes[index + 1]; + updatedCurrentNotes[index + 1] = updatedCurrentNotes[index]; + updatedCurrentNotes[index] = temp2; + + documentationResponse.current = { + ...documentationResponse.current, + Notes: JSON.stringify(updatedCurrentNotes), + }; + }} + onDelete={() => { + if (notes.length === 1) { + setNotes([EmptyNote]); + return; + } + + const updatedNotes = [...notes]; + updatedNotes.splice(index, 1); + + setNotes(updatedNotes); + }} + /> + ))} + + + } + onClick={handleAddNote} + > + Add note + + + + ); +} + +function UploadComponent({ setImagePreview }) { + const handleBeforeUpload = (file) => { + if ( + !Constants.ACCEPTED_EQUIPMENT_DOCUMENTATION_FILE_TYPES.includes(file.type) + ) { + message.error(`${file.name} is not valid file type`); + return false; + } + + const reader = new FileReader(); + reader.onload = () => setImagePreview(reader.result); + reader.readAsDataURL(file); + + return false; + }; + + return ( + + + + ); +} + +function CameraComponent({ setImagePreview }) { + const [modalVisible, setModalVisible] = useState(false); + const [cameraVisible, setCameraVisible] = useState(false); + const webcamRef = useRef(null); + + const handleCapture = () => { + const imageSrc = webcamRef.current.getScreenshot(); + setImagePreview(imageSrc); + + handleCancel(); + }; + + const handleCancel = () => { + setCameraVisible(false); + // this is needed to close the camera correctly + setTimeout(() => setModalVisible(false), 100); + }; + + return ( + <> + { + setModalVisible(true); + setCameraVisible(true); + }} + > + + + + + Take picture + , + ]} + > + {cameraVisible && ( + + )} + + > + ); +} + +function MoreComponent({ onMoveUp, onMoveDown, onDelete }) { + return ( + + + + Move up + + + ), + key: "1", + }, + { + label: ( + + + + Move down + + + ), + key: "2", + }, + { + label: ( + + + + Delete note + + + ), + key: "0", + }, + ], + }} + > + + + ); +} + +export function NoteComponent({ + viewMode, + image, + onImageChange, + description, + onDescriptionChange, + onDeleteImage, + documentationId, + onMoveUp, + onMoveDown, + onDelete, +}) { + const [isImageFullScreenModalOpen, setIsImageFullScreenModalOpen] = + useState(false); + + const imageSrc = viewMode + ? `${Constants.STATIC_CONTENT_ADDRESS}equipmentdocumentation/${documentationId}/${image}` + : image; + + const FullscreenOutlinedIcon = ({ disabled }) => ( + { + if (disabled) return; + + setIsImageFullScreenModalOpen(true); + }} + /> + ); + + return ( + + + + ] + : null + : [ + , + , + , + , + , + ] + } + > + {!image ? ( + + {viewMode ? "No image" : "No image selected"} + + ) : ( + + )} + + + + + {viewMode ? ( + {description} + ) : ( + + )} + + + + setIsImageFullScreenModalOpen(false)} + image={imageSrc} + /> + + ); +} + +function ImageFullscreenModal({ isOpen, onCancel, image }) { + return ( + + + + ); +} diff --git a/src/utils.js b/src/utils.js index 95b7976..a01f0a2 100644 --- a/src/utils.js +++ b/src/utils.js @@ -77,6 +77,11 @@ export const Constants = { "image/jpg", "image/gif", ], + ACCEPTED_EQUIPMENT_DOCUMENTATION_FILE_TYPES: [ + "image/png", + "image/jpeg", + "image/jpg", + ], PERMISSIONS: { EQUIPMENT_DOCUMENTATION: { VIEW: "equipment_documentation.view",
- ID: {documentation.Id} - - Type: {documentation.Type} - - Created at: {FormatDatetime(documentation.CreatedAt)} - - Updated at: {FormatDatetime(documentation.UpdatedAt)} -