refactor: moves pdf marking and rendering one level down

This commit is contained in:
eugene 2024-08-02 11:43:51 +01:00
parent e1808726aa
commit 87ef61a28e
7 changed files with 159 additions and 71 deletions

View File

@ -6,11 +6,11 @@ interface PdfItemProps {
pdfFile: PdfFile pdfFile: PdfFile
currentUserMarks: CurrentUserMark[] currentUserMarks: CurrentUserMark[]
handleMarkClick: (id: number) => void handleMarkClick: (id: number) => void
currentMarkValue: string selectedMarkValue: string
currentUserMark: CurrentUserMark | null selectedMark: CurrentUserMark | null
} }
const PdfItem = ({ pdfFile, currentUserMarks, handleMarkClick, currentMarkValue, currentUserMark }: PdfItemProps) => { const PdfItem = ({ pdfFile, currentUserMarks, handleMarkClick, selectedMarkValue, selectedMark }: PdfItemProps) => {
const filterByPage = (marks: CurrentUserMark[], page: number): CurrentUserMark[] => { const filterByPage = (marks: CurrentUserMark[], page: number): CurrentUserMark[] => {
return marks.filter((m) => m.mark.location.page === page); return marks.filter((m) => m.mark.location.page === page);
} }
@ -20,10 +20,10 @@ const PdfItem = ({ pdfFile, currentUserMarks, handleMarkClick, currentMarkValue,
<PdfPageItem <PdfPageItem
page={page} page={page}
key={i} key={i}
marks={filterByPage(currentUserMarks, i)} currentUserMarks={filterByPage(currentUserMarks, i)}
handleMarkClick={handleMarkClick} handleMarkClick={handleMarkClick}
currentMarkValue={currentMarkValue} selectedMarkValue={selectedMarkValue}
currentUserMark={currentUserMark} selectedMark={selectedMark}
/> />
) )
})) }))

View File

@ -1,31 +1,35 @@
import { CurrentUserMark, Mark, MarkLocation } from '../../types/mark.ts' import { CurrentUserMark } from '../../types/mark.ts'
import styles from '../DrawPDFFields/style.module.scss' import styles from '../DrawPDFFields/style.module.scss'
import { inPx } from '../../utils/pdf.ts' import { inPx } from '../../utils/pdf.ts'
interface PdfMarkItemProps { interface PdfMarkItemProps {
mark: Mark userMark: CurrentUserMark
handleMarkClick: (id: number) => void handleMarkClick: (id: number) => void
isEditable: boolean selectedMarkValue: string
currentMarkValue: string selectedMark: CurrentUserMark | null
currentUserMark: CurrentUserMark | null
} }
const PdfMarkItem = ({ mark, handleMarkClick, isEditable, currentMarkValue, currentUserMark }: PdfMarkItemProps) => { //selectedMark represents the mark that the user is actively editing
const handleClick = () => isEditable && handleMarkClick(mark.id); // selectedMarkValue representsnthe edited value
// userMark is part of the overall currentUserMark array
const PdfMarkItem = ({ selectedMark, handleMarkClick, selectedMarkValue, userMark }: PdfMarkItemProps) => {
const { location } = userMark.mark;
const handleClick = () => handleMarkClick(userMark.mark.id);
const getMarkValue = () => ( const getMarkValue = () => (
currentUserMark?.mark.id === mark.id selectedMark?.mark.id === userMark.mark.id
? currentMarkValue ? selectedMarkValue
: mark.value : userMark.mark.value
) )
return ( return (
<div <div
onClick={handleClick} onClick={handleClick}
className={`${styles.drawingRectangle} ${isEditable ? '' : styles.nonEditable}`} className={styles.drawingRectangle}
style={{ style={{
left: inPx(mark.location.left), left: inPx(location.left),
top: inPx(mark.location.top), top: inPx(location.top),
width: inPx(mark.location.width), width: inPx(location.width),
height: inPx(mark.location.height) height: inPx(location.height)
}} }}
>{getMarkValue()}</div> >{getMarkValue()}</div>
) )

View File

@ -0,0 +1,95 @@
import { Box } from '@mui/material'
import styles from '../../pages/sign/style.module.scss'
import PdfView from './index.tsx'
import MarkFormField from '../../pages/sign/MarkFormField.tsx'
import { PdfFile } from '../../types/drawing.ts'
import { CurrentUserMark, Mark } from '../../types/mark.ts'
import { useState, useEffect } from 'react'
import {
findNextCurrentUserMark,
isCurrentUserMarksComplete,
updateCurrentUserMarks,
} from '../../utils/mark.ts'
import { EMPTY } from '../../utils/const.ts'
interface PdfMarkingProps {
files: { pdfFile: PdfFile, filename: string, hash: string | null }[],
currentUserMarks: CurrentUserMark[],
setIsReadyToSign: (isReadyToSign: boolean) => void,
setCurrentUserMarks: (currentUserMarks: CurrentUserMark[]) => void,
setUpdatedMarks: (markToUpdate: Mark) => void
}
const PdfMarking = (props: PdfMarkingProps) => {
const {
files,
currentUserMarks,
setIsReadyToSign,
setCurrentUserMarks,
setUpdatedMarks
} = props
const [selectedMark, setSelectedMark] = useState<CurrentUserMark | null>(null)
const [selectedMarkValue, setSelectedMarkValue] = useState<string>("")
useEffect(() => {
setSelectedMark(findNextCurrentUserMark(currentUserMarks) || null)
}, [currentUserMarks])
const handleMarkClick = (id: number) => {
const nextMark = currentUserMarks.find((mark) => mark.mark.id === id);
setSelectedMark(nextMark!);
setSelectedMarkValue(nextMark?.mark.value ?? EMPTY);
}
const handleSubmit = (event: any) => {
event.preventDefault();
if (!selectedMarkValue || !selectedMark) return;
const updatedMark: CurrentUserMark = {
...selectedMark,
mark: {
...selectedMark.mark,
value: selectedMarkValue
},
isCompleted: true
}
setSelectedMarkValue(EMPTY)
const updatedCurrentUserMarks = updateCurrentUserMarks(currentUserMarks, updatedMark);
setCurrentUserMarks(updatedCurrentUserMarks)
setSelectedMark(findNextCurrentUserMark(updatedCurrentUserMarks) || null)
console.log(isCurrentUserMarksComplete(updatedCurrentUserMarks))
setIsReadyToSign(isCurrentUserMarksComplete(updatedCurrentUserMarks))
setUpdatedMarks(updatedMark.mark)
}
const handleChange = (event: any) => setSelectedMarkValue(event.target.value)
return (
<>
<Box className={styles.container}>
{
currentUserMarks?.length > 0 && (
<PdfView
files={files}
handleMarkClick={handleMarkClick}
selectedMarkValue={selectedMarkValue}
selectedMark={selectedMark}
currentUserMarks={currentUserMarks}
/>)}
{
selectedMark !== null && (
<MarkFormField
handleSubmit={handleSubmit}
handleChange={handleChange}
selectedMark={selectedMark}
selectedMarkValue={selectedMarkValue}
/>
)}
</Box>
</>
)
}
export default PdfMarking

View File

@ -1,24 +1,16 @@
import styles from '../DrawPDFFields/style.module.scss' import styles from '../DrawPDFFields/style.module.scss'
import { PdfPage } from '../../types/drawing.ts' import { PdfPage } from '../../types/drawing.ts'
import { CurrentUserMark, Mark, MarkConfigDetails } from '../../types/mark.ts' import { CurrentUserMark } from '../../types/mark.ts'
import PdfMarkItem from './PdfMarkItem.tsx' import PdfMarkItem from './PdfMarkItem.tsx'
import { useSelector } from 'react-redux'
import { State } from '../../store/rootReducer.ts'
import { hexToNpub } from '../../utils'
interface PdfPageProps { interface PdfPageProps {
page: PdfPage page: PdfPage
marks: Mark[] currentUserMarks: CurrentUserMark[]
handleMarkClick: (id: number) => void handleMarkClick: (id: number) => void
currentMarkValue: string selectedMarkValue: string
currentUserMark: CurrentUserMark | null selectedMark: CurrentUserMark | null
} }
const PdfPageItem = ({ page, marks, handleMarkClick, currentMarkValue, currentUserMark }: PdfPageProps) => { const PdfPageItem = ({ page, currentUserMarks, handleMarkClick, selectedMarkValue, selectedMark }: PdfPageProps) => {
const usersPubkey = useSelector((state: State) => state.auth.usersPubkey)
const isEditable = (mark: Mark): boolean => {
if (!usersPubkey) return false;
return mark.npub === hexToNpub(usersPubkey);
}
return ( return (
<div <div
className={styles.pdfImageWrapper} className={styles.pdfImageWrapper}
@ -35,14 +27,13 @@ const PdfPageItem = ({ page, marks, handleMarkClick, currentMarkValue, currentUs
/> />
{ {
marks.map((mark, i) => ( currentUserMarks.map((m, i) => (
<PdfMarkItem <PdfMarkItem
key={i} key={i}
mark={mark}
isEditable={isEditable(mark)}
handleMarkClick={handleMarkClick} handleMarkClick={handleMarkClick}
currentMarkValue={currentMarkValue} selectedMarkValue={selectedMarkValue}
currentUserMark={currentUserMark} userMark={m}
selectedMark={selectedMark}
/> />
))} ))}
</div> </div>

View File

@ -1,37 +1,39 @@
import { PdfFile } from '../../types/drawing.ts' import { PdfFile } from '../../types/drawing.ts'
import { Box } from '@mui/material' import { Box } from '@mui/material'
import PdfItem from './PdfItem.tsx' import PdfItem from './PdfItem.tsx'
import { CurrentUserMark, Mark, MarkConfigDetails } from '../../types/mark.ts' import { CurrentUserMark } from '../../types/mark.ts'
interface PdfViewProps { interface PdfViewProps {
files: { [filename: string]: PdfFile }, files: { pdfFile: PdfFile, filename: string, hash: string | null }[]
fileHashes: { [key: string]: string | null }, currentUserMarks: CurrentUserMark[]
marks: Mark[],
handleMarkClick: (id: number) => void handleMarkClick: (id: number) => void
currentMarkValue: string selectedMarkValue: string
currentUserMark: CurrentUserMark | null selectedMark: CurrentUserMark | null
} }
const PdfView = ({ files, fileHashes, marks, handleMarkClick, currentMarkValue, currentUserMark }: PdfViewProps) => { const PdfView = ({ files, currentUserMarks, handleMarkClick, selectedMarkValue, selectedMark }: PdfViewProps) => {
const filterByFile = (marks: Mark[], fileHash: string): Mark[] => { const filterByFile = (currentUserMarks: CurrentUserMark[], hash: string): CurrentUserMark[] => {
return marks.filter((mark) => mark.pdfFileHash === fileHash); return currentUserMarks.filter((currentUserMark) => currentUserMark.mark.pdfFileHash === hash)
} }
return ( return (
<Box sx={{ width: '100%' }}> <Box sx={{ width: '100%' }}>
{Object.entries(files) {
.map(([name, file], i) => ( files.map(({ pdfFile, hash }, i) => {
<PdfItem if (!hash) return
pdfFile={file} return (
key={i} <PdfItem
marks={filterByFile(marks, fileHashes[name] ?? "")} pdfFile={pdfFile}
handleMarkClick={handleMarkClick} key={i}
currentMarkValue={currentMarkValue} currentUserMarks={filterByFile(currentUserMarks, hash)}
currentUserMark={currentUserMark} selectedMark={selectedMark}
handleMarkClick={handleMarkClick}
selectedMarkValue={selectedMarkValue}
/> />
))} )
})
}
</Box> </Box>
) )
} }
export default PdfView; export default PdfView;

View File

@ -1,25 +1,26 @@
import { CurrentUserMark, Mark } from '../../types/mark.ts' import { CurrentUserMark, Mark } from '../../types/mark.ts'
import styles from './style.module.scss' import styles from './style.module.scss'
import { Box, Button, TextField } from '@mui/material' import { Box, Button, TextField } from '@mui/material'
import { MarkTypeTranslation } from './const.ts'
import { MARK_TYPE_TRANSLATION } from '../../utils/const.ts'
interface MarkFormFieldProps { interface MarkFormFieldProps {
handleSubmit: (event: any) => void handleSubmit: (event: any) => void
handleChange: (event: any) => void handleChange: (event: any) => void
currentMark: CurrentUserMark selectedMark: CurrentUserMark
currentMarkValue: string selectedMarkValue: string
} }
const MarkFormField = (props: MarkFormFieldProps) => { const MarkFormField = (props: MarkFormFieldProps) => {
const { handleSubmit, handleChange, currentMark, currentMarkValue } = props; const { handleSubmit, handleChange, selectedMark, selectedMarkValue } = props;
const getSubmitButton = () => currentMark.isLast ? 'Complete' : 'Next'; const getSubmitButton = () => selectedMark.isLast ? 'Complete' : 'Next';
return ( return (
<div className={styles.fixedBottomForm}> <div className={styles.fixedBottomForm}>
<Box component="form" onSubmit={handleSubmit}> <Box component="form" onSubmit={handleSubmit}>
<TextField <TextField
id="mark-value" id="mark-value"
label={MarkTypeTranslation[currentMark.mark.type.valueOf()]} label={MARK_TYPE_TRANSLATION[selectedMark.mark.type.valueOf()]}
value={currentMarkValue} value={selectedMarkValue}
onChange={handleChange} onChange={handleChange}
/> />
<Button type="submit" variant="contained"> <Button type="submit" variant="contained">

View File

@ -1,5 +0,0 @@
import { MarkType } from '../../types/drawing.ts'
export const MarkTypeTranslation: { [key: string]: string } = {
[MarkType.FULLNAME.valueOf()]: "Full Name"
}