Created
August 10, 2021 17:28
-
-
Save jordanhudgens/26e444b09f9a4066cbee549796aa50c1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from "react"; | |
import { | |
DTCheckbox, | |
DTTextField, | |
DTToggle, | |
Heading, | |
Pane, | |
PaneAccordianContainer, | |
PaneAccordionItem, | |
PaneContentContainer, | |
} from "@dashtrack/web-utility"; | |
import { SketchPicker, ColorResult } from "react-color"; | |
import { IPageCategory, MediaRecordType } from "@dashtrack/types"; | |
import { formatErrors } from "@dashtrack/text-utility"; | |
import QRCode from "qrcode.react"; | |
import AppStateContext from "../../contexts/AppStateContext"; | |
import PageManagerContext from "../../contexts/PageManagerContext"; | |
import NotificationContext from "../../contexts/NotificationContext"; | |
import { colorPrimary, paneTheme } from "../../../utils/colors"; | |
import { orgApi } from "../../../utils/api"; | |
import CurrentUserContext from "../../contexts/CurrentUserContext"; | |
import MediaManager from "../organizations/media-records/MediaManager"; | |
interface IQrCodePane { | |
isOpen: boolean; | |
handleClose: () => void; | |
pageCategory: IPageCategory; | |
} | |
export default function QrCodePane({ | |
isOpen, | |
handleClose, | |
pageCategory, | |
}: IQrCodePane) { | |
const qrRef = React.useRef(); | |
// Attempt this fix: | |
// https://github.com/zpao/qrcode.react/issues/143 | |
const { organizationLogo } = React.useContext(CurrentUserContext); | |
const { paneWidth } = React.useContext(AppStateContext); | |
const [url, setUrl] = React.useState(undefined); | |
const { handlePageCategoryFormSubmission } = | |
React.useContext(PageManagerContext); | |
const { showErrorNotification } = React.useContext(NotificationContext); | |
const [isUpdatingQrDestination, setIsUpdatingQrDestination] = | |
React.useState(false); | |
const [embedMedia, setEmbedMedia] = React.useState(false); | |
const [imageSize, setImageSize] = React.useState("1000"); | |
const [qrCode, setQrCode] = React.useState(undefined); | |
const [fgColor, setFgColor] = React.useState("#000000"); | |
const [bgColor, setBgColor] = React.useState("#FFFFFF"); | |
const [levelType, setLevelType] = React.useState<"L" | "M" | "Q" | "H">("L"); | |
const [includeMargin, setIncludeMargin] = React.useState(true); | |
const [mediaRecordsToAssign, setMediaRecordsToAssign] = React.useState< | |
MediaRecordType[] | |
>([]); | |
React.useEffect(() => { | |
if (pageCategory?.qr_code_url) setUrl(pageCategory.qr_code_url); | |
}, [pageCategory, pageCategory?.qr_code_url]); | |
const updateQrDestination = (updatedQrDestination: any) => { | |
setIsUpdatingQrDestination(true); | |
const params = { | |
page_category: { | |
qr_destination: updatedQrDestination, | |
}, | |
}; | |
orgApi | |
.patch(`page_categories/${pageCategory?.token}`, params) | |
.then( | |
(response: { | |
data: { page_category: IPageCategory; errors?: any }; | |
}) => { | |
const { page_category, errors } = response.data; | |
setIsUpdatingQrDestination(false); | |
if (page_category) { | |
handlePageCategoryFormSubmission(page_category); | |
} else if (errors) { | |
showErrorNotification({ | |
title: formatErrors(errors), | |
}); | |
} else { | |
showErrorNotification({ | |
title: "Error updating QR code URL", | |
}); | |
} | |
} | |
) | |
.catch((_error) => { | |
setIsUpdatingQrDestination(false); | |
showErrorNotification({ | |
title: "Error updating QR code URL", | |
}); | |
}); | |
}; | |
const downloadQRCode = () => { | |
// @ts-ignore | |
let canvas = qrRef.current.querySelector("canvas"); | |
let image = canvas.toDataURL("image/png"); | |
let anchor = document.createElement("a"); | |
anchor.href = image; | |
anchor.download = `${pageCategory.name}-qr-code.png`; | |
document.body.appendChild(anchor); | |
anchor.click(); | |
document.body.removeChild(anchor); | |
}; | |
const handleBgColorChange = (color: ColorResult) => { | |
const rgbaValue = `rgba(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b}, ${color.rgb.a})`; | |
setBgColor(rgbaValue); | |
}; | |
const handleFgColorChange = (color: ColorResult) => { | |
const rgbaValue = `rgba(${color.rgb.r}, ${color.rgb.g}, ${color.rgb.b}, ${color.rgb.a})`; | |
console.log("UPDATD FG", rgbaValue); | |
setFgColor(rgbaValue); | |
}; | |
const qrCodeRenderer = ( | |
<div | |
className="qr-code-form-container" | |
style={{ margin: "5px 0px 21px 0px" }} | |
> | |
<QRCode | |
id="qrCodeElToRender" | |
size={470} | |
value={url} | |
bgColor={bgColor} | |
fgColor={fgColor} | |
includeMargin={includeMargin} | |
level={levelType} | |
imageSettings={ | |
embedMedia | |
? { | |
src: organizationLogo, | |
excavate: true, | |
} | |
: undefined | |
} | |
/> | |
<div | |
style={{ | |
visibility: "hidden", | |
position: "absolute", | |
overflow: "hidden", | |
width: "0px", | |
height: "0px", | |
}} | |
ref={qrRef} | |
> | |
<QRCode | |
id="qrCodeElToDownload" | |
size={parseInt(imageSize)} | |
value={url} | |
bgColor={bgColor} | |
fgColor={fgColor} | |
includeMargin={includeMargin} | |
level={levelType} | |
imageSettings={ | |
embedMedia | |
? { | |
// src: organizationLogo, | |
src: "https://static.zpao.com/favicon.png", | |
excavate: true, | |
x: null, | |
y: null, | |
width: 100, | |
height: 100, | |
} | |
: undefined | |
} | |
/> | |
</div> | |
</div> | |
); | |
const destinationAccordion = ( | |
<PaneAccordionItem showTopBorder label="URL destination"> | |
<DTTextField | |
value={url} | |
name="URL" | |
setValue={setUrl} | |
handleSubmit={updateQrDestination} | |
isSaving={isUpdatingQrDestination} | |
clickToEdit | |
/> | |
</PaneAccordionItem> | |
); | |
const layoutAccordion = ( | |
<PaneAccordionItem showTopBorder label="Layout"> | |
<DTTextField | |
value={imageSize} | |
name="Size in pixels" | |
setValue={setImageSize} | |
handleSubmit={() => console.log("Updated size")} | |
isSaving={false} | |
clickToEdit | |
/> | |
<DTToggle | |
value={includeMargin} | |
onChange={setIncludeMargin} | |
label="Include margin?" | |
/> | |
<div className="flex-space-between"> | |
<Heading size="sm" color={colorPrimary} fontWeight={700}> | |
Design type | |
</Heading> | |
<DTCheckbox | |
checked={levelType === "L"} | |
onChange={() => setLevelType("L")} | |
label="L" | |
/> | |
<DTCheckbox | |
checked={levelType === "M"} | |
onChange={() => setLevelType("M")} | |
label="M" | |
/> | |
<DTCheckbox | |
checked={levelType === "H"} | |
onChange={() => setLevelType("H")} | |
label="H" | |
/> | |
<DTCheckbox | |
checked={levelType === "Q"} | |
onChange={() => setLevelType("Q")} | |
label="Q" | |
/> | |
</div> | |
</PaneAccordionItem> | |
); | |
const bgColorAccordion = ( | |
<PaneAccordionItem showTopBorder label="Colors"> | |
<div className="grid-2"> | |
<div className="grid-1" style={{ alignItems: "center" }}> | |
<Heading size="sm" color={colorPrimary} fontWeight={700}> | |
Background | |
</Heading> | |
<SketchPicker | |
color={bgColor} | |
onChangeComplete={handleBgColorChange} | |
/> | |
</div> | |
<div className="grid-1" style={{ alignItems: "center" }}> | |
<Heading size="sm" color={colorPrimary} fontWeight={700}> | |
Foreground | |
</Heading> | |
<SketchPicker | |
color={fgColor} | |
onChangeComplete={handleFgColorChange} | |
/> | |
</div> | |
</div> | |
</PaneAccordionItem> | |
); | |
const mediaAccordionElement = ( | |
<PaneAccordionItem label="Media" showTopBorder showBottomBorder> | |
<DTToggle | |
value={embedMedia} | |
onChange={setEmbedMedia} | |
label="Embed media?" | |
/> | |
{embedMedia && ( | |
<MediaManager | |
mediaRecordsToAssign={mediaRecordsToAssign} | |
setMediaRecordsToAssign={setMediaRecordsToAssign} | |
resourceData={{ | |
resource_name: "QrCode", | |
resource_id: qrCode?.id, | |
}} | |
/> | |
)} | |
</PaneAccordionItem> | |
); | |
return ( | |
<Pane | |
isOpen={isOpen} | |
handleClose={handleClose} | |
staticTitle="QR Generator" | |
paneWidth={paneWidth} | |
paneType="CONTENT" | |
theme={paneTheme} | |
actions={[ | |
<a className="font-bold primary" onClick={downloadQRCode}> | |
Download | |
</a>, | |
]} | |
> | |
<PaneContentContainer>{qrCodeRenderer}</PaneContentContainer> | |
<PaneAccordianContainer> | |
{bgColorAccordion} | |
{destinationAccordion} | |
{layoutAccordion} | |
{mediaAccordionElement} | |
</PaneAccordianContainer> | |
</Pane> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment