app/javascript/components/Attachments/AttachmentEditor.tsx
import { ChangeEvent, MouseEvent, useState } from "react";import copyToClipboard, { copySupported } from "../../lib/copyToClipboard";import useModalStore from "../../stores/useModalStore";import useToastStore from "../../stores/useToastStore";import { putJson } from "../../lib/request";import * as Attachments from "../../types/Attachments";import { Locale } from "../../types"; type Props = { attachment: Attachments.Resource; locale: string; locales: { [index: string]: Locale }; onUpdate: (attachment: Partial<Attachments.Resource>) => void;}; Function `AttachmentEditor` has 93 lines of code (exceeds 25 allowed). Consider refactoring.
Function `AttachmentEditor` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.export default function AttachmentEditor(props: Props) { const { attachment, locales } = props; const [locale, setLocale] = useState(props.locale); const [localizations, setLocalizations] = useState({ name: attachment.name || {}, description: attachment.description || {} }); const notice = useToastStore((state) => state.notice); const closeModal = useModalStore((state) => state.close); const updateLocalization = (name: "name" | "description") => (evt: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLTextAreaElement>) => { setLocalizations({ ...localizations, [name]: { ...localizations[name], [locale]: evt.target.value } }); }; Similar blocks of code found in 3 locations. Consider refactoring. const copyEmbedCode = (evt: MouseEvent) => { evt.preventDefault(); copyToClipboard(`[attachment:${attachment.id}]`); notice("Embed code copied to clipboard"); }; const save = async (evt: MouseEvent) => { evt.preventDefault(); evt.stopPropagation(); const data = { ...localizations }; await putJson(`/admin/attachments/${attachment.id}`, { attachment: data }); if (props.onUpdate) { props.onUpdate(data); } closeModal(); }; const inputDir = (locales && locales[locale] && locales[locale].dir) || "ltr"; return ( <div className="attachment-editor"> <form> {props.locales && Object.keys(locales).length > 1 && ( <div className="field"> <label>Locale</label>Similar blocks of code found in 2 locations. Consider refactoring. <select name="locale" value={locale} onChange={(e) => setLocale(e.target.value)}> {Object.keys(locales).map((key) => ( <option key={`locale-${key}`} value={key}> {locales[key].name} </option> ))} </select> </div> )} <div className="field"> <label>Name</label> <input type="text" className="name" lang={locale} dir={inputDir} value={localizations.name[locale] || ""} onChange={updateLocalization("name")} /> </div> <div className="field"> <label>Description</label> <textarea className="description" value={localizations.description[locale] || ""} lang={locale} dir={inputDir} onChange={updateLocalization("description")} /> </div>Similar blocks of code found in 2 locations. Consider refactoring. <div className="field embed-code"> <label>Embed code</label> <input type="text" value={`[attachment:${attachment.id}]`} disabled={true} /> {copySupported() && <button onClick={copyEmbedCode}>Copy</button>} </div> <div className="field"> <label>File</label> <a href={attachment.url} rel="noreferrer" target="_blank"> {attachment.filename} </a> </div> <div className="buttons"> <button onClick={save}>Save</button> <button onClick={closeModal}>Cancel</button> </div> </form> </div> );}