PDF Markings #114
@ -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}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
|
@ -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>
|
||||||
)
|
)
|
||||||
|
@ -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
|
@ -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>
|
||||||
|
@ -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) => {
|
||||||
|
if (!hash) return
|
||||||
|
return (
|
||||||
<PdfItem
|
<PdfItem
|
||||||
pdfFile={file}
|
pdfFile={pdfFile}
|
||||||
key={i}
|
key={i}
|
||||||
marks={filterByFile(marks, fileHashes[name] ?? "")}
|
currentUserMarks={filterByFile(currentUserMarks, hash)}
|
||||||
|
selectedMark={selectedMark}
|
||||||
handleMarkClick={handleMarkClick}
|
handleMarkClick={handleMarkClick}
|
||||||
currentMarkValue={currentMarkValue}
|
selectedMarkValue={selectedMarkValue}
|
||||||
currentUserMark={currentUserMark}
|
|
||||||
/>
|
/>
|
||||||
))}
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PdfView;
|
export default PdfView;
|
@ -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">
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
import { MarkType } from '../../types/drawing.ts'
|
|
||||||
|
|
||||||
export const MarkTypeTranslation: { [key: string]: string } = {
|
|
||||||
[MarkType.FULLNAME.valueOf()]: "Full Name"
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user