Releasing new design #161
@ -59,14 +59,18 @@
|
||||
.drawingRectangle {
|
||||
position: absolute;
|
||||
border: 1px solid #01aaad;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
//width: 40px;
|
||||
//height: 40px;
|
||||
z-index: 50;
|
||||
background-color: #01aaad4b;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
&.nonEditable {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.resizeHandle {
|
||||
position: absolute;
|
||||
right: -5px;
|
||||
|
@ -1,25 +1,25 @@
|
||||
import { PdfFile } from '../../types/drawing.ts'
|
||||
import { MarkConfigDetails} from '../../types/mark.ts'
|
||||
import { Mark, MarkConfigDetails } from '../../types/mark.ts'
|
||||
import PdfPageItem from './PdfPageItem.tsx';
|
||||
|
||||
interface PdfItemProps {
|
||||
pdfFile: PdfFile
|
||||
markConfigDetails: MarkConfigDetails[]
|
||||
marks: Mark[]
|
||||
handleMarkClick: (id: number) => void
|
||||
}
|
||||
|
||||
const PdfItem = ({ pdfFile, markConfigDetails }: PdfItemProps) => {
|
||||
const filterMarkConfigDetails = (i: number) => {
|
||||
return markConfigDetails.filter(
|
||||
(details) => details.markLocation.page === i);
|
||||
const PdfItem = ({ pdfFile, marks, handleMarkClick }: PdfItemProps) => {
|
||||
const filterByPage = (marks: Mark[], page: number): Mark[] => {
|
||||
return marks.filter((mark) => mark.location.page === page);
|
||||
}
|
||||
return (
|
||||
pdfFile.pages.map((page, i) => {
|
||||
console.log('page: ', page);
|
||||
return (
|
||||
<PdfPageItem
|
||||
page={page}
|
||||
key={i}
|
||||
markConfigDetails={filterMarkConfigDetails(i)}
|
||||
marks={filterByPage(marks, i)}
|
||||
handleMarkClick={handleMarkClick}
|
||||
/>
|
||||
)
|
||||
}))
|
||||
|
@ -1,20 +1,24 @@
|
||||
import { MarkLocation } from '../../types/mark.ts'
|
||||
import { Mark, MarkLocation } from '../../types/mark.ts'
|
||||
import styles from '../DrawPDFFields/style.module.scss'
|
||||
import { inPx } from '../../utils/pdf.ts'
|
||||
|
||||
interface PdfMarkItemProps {
|
||||
markLocation: MarkLocation
|
||||
mark: Mark
|
||||
handleMarkClick: (id: number) => void
|
||||
isEditable: boolean
|
||||
}
|
||||
|
||||
const PdfMarkItem = ({ markLocation }: PdfMarkItemProps) => {
|
||||
const PdfMarkItem = ({ mark, handleMarkClick, isEditable }: PdfMarkItemProps) => {
|
||||
const handleClick = () => isEditable && handleMarkClick(mark.id);
|
||||
return (
|
||||
<div
|
||||
className={styles.drawingRectangle}
|
||||
onClick={handleClick}
|
||||
className={`${styles.drawingRectangle} ${isEditable ? '' : styles.nonEditable}`}
|
||||
style={{
|
||||
left: inPx(markLocation.left),
|
||||
top: inPx(markLocation.top),
|
||||
width: inPx(markLocation.width),
|
||||
height: inPx(markLocation.height)
|
||||
left: inPx(mark.location.left),
|
||||
top: inPx(mark.location.top),
|
||||
width: inPx(mark.location.width),
|
||||
height: inPx(mark.location.height)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
@ -1,27 +1,45 @@
|
||||
import styles from '../DrawPDFFields/style.module.scss'
|
||||
import { PdfPage } from '../../types/drawing.ts'
|
||||
import { MarkConfigDetails, MarkLocation } from '../../types/mark.ts'
|
||||
import { Mark, MarkConfigDetails } from '../../types/mark.ts'
|
||||
import PdfMarkItem from './PdfMarkItem.tsx'
|
||||
import { useState } from 'react';
|
||||
import { useSelector } from 'react-redux'
|
||||
import { State } from '../../store/rootReducer.ts'
|
||||
import { hexToNpub } from '../../utils'
|
||||
interface PdfPageProps {
|
||||
page: PdfPage
|
||||
markConfigDetails: MarkConfigDetails[]
|
||||
marks: Mark[]
|
||||
handleMarkClick: (id: number) => void
|
||||
}
|
||||
|
||||
const PdfPageItem = ({ page, markConfigDetails }: PdfPageProps) => {
|
||||
const [currentMark, setCurrentMark] = useState<MarkLocation | null>(null);
|
||||
|
||||
const PdfPageItem = ({ page, marks, handleMarkClick }: PdfPageProps) => {
|
||||
const usersPubkey = useSelector((state: State) => state.auth.usersPubkey)
|
||||
const isEditable = (mark: Mark): boolean => {
|
||||
if (!usersPubkey) return false;
|
||||
return mark.npub === hexToNpub(usersPubkey);
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className={styles.pdfImageWrapper}
|
||||
style={{
|
||||
border: '1px solid #c4c4c4',
|
||||
marginBottom: '10px'
|
||||
marginBottom: '10px',
|
||||
marginTop: '10px'
|
||||
}}
|
||||
className={styles.pdfImageWrapper}
|
||||
>
|
||||
<img draggable="false" style={{width: '100%'}} src={page.image} />
|
||||
{markConfigDetails.map((detail, i) => (
|
||||
<PdfMarkItem key={i} markLocation={detail.markLocation} />
|
||||
<img
|
||||
draggable="false"
|
||||
src={page.image}
|
||||
style={{ width: '100%'}}
|
||||
|
||||
/>
|
||||
{
|
||||
marks.map((mark, i) => (
|
||||
<PdfMarkItem
|
||||
key={i}
|
||||
mark={mark}
|
||||
isEditable={isEditable(mark)}
|
||||
handleMarkClick={handleMarkClick}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
|
@ -1,41 +1,29 @@
|
||||
import { PdfFile } from '../../types/drawing.ts'
|
||||
import { Box } from '@mui/material'
|
||||
import PdfItem from './PdfItem.tsx'
|
||||
import { MarkConfig, MarkConfigDetails } from '../../types/mark.ts'
|
||||
import { State } from '../../store/rootReducer'
|
||||
import { useSelector } from 'react-redux';
|
||||
import { hexToNpub, npubToHex } from '../../utils'
|
||||
import { Mark, MarkConfigDetails } from '../../types/mark.ts'
|
||||
|
||||
interface PdfViewProps {
|
||||
files: { [filename: string]: PdfFile },
|
||||
fileHashes: { [key: string]: string | null },
|
||||
markConfig: MarkConfig,
|
||||
marks: Mark[],
|
||||
handleMarkClick: (id: number) => void
|
||||
}
|
||||
|
||||
const PdfView = (props: PdfViewProps) => {
|
||||
console.log('current file hashes: ', props.fileHashes)
|
||||
const usersPubkey = useSelector((state: State) => state.auth.usersPubkey);
|
||||
if (!usersPubkey) return;
|
||||
console.log(props.markConfig[hexToNpub(usersPubkey)]);
|
||||
|
||||
console.log('users pubkey: ', usersPubkey);
|
||||
console.log('mark config: ', props.markConfig);
|
||||
|
||||
const getMarkConfigDetails = (fileName: string): MarkConfigDetails[] | undefined => {
|
||||
const fileHash = props.fileHashes[fileName];
|
||||
if (!fileHash) return;
|
||||
return props.markConfig[hexToNpub(usersPubkey)][fileHash];
|
||||
const PdfView = ({ files, fileHashes, marks, handleMarkClick }: PdfViewProps) => {
|
||||
const filterByFile = (marks: Mark[], fileHash: string): Mark[] => {
|
||||
return marks.filter((mark) => mark.pdfFileHash === fileHash);
|
||||
}
|
||||
const { files } = props;
|
||||
return (
|
||||
<Box>
|
||||
<Box sx={{ width: '100%' }}>
|
||||
{Object.entries(files)
|
||||
.filter(([name]) => !!getMarkConfigDetails(name))
|
||||
.map(([name, file], i) => (
|
||||
<PdfItem
|
||||
pdfFile={file}
|
||||
key={i}
|
||||
markConfigDetails={getMarkConfigDetails(name) as MarkConfigDetails[]} />
|
||||
marks={filterByFile(marks, fileHashes[name] ?? "")}
|
||||
handleMarkClick={handleMarkClick}
|
||||
/>
|
||||
))}
|
||||
</Box>
|
||||
)
|
||||
|
16
src/components/PDFView/style.module.scss
Normal file
16
src/components/PDFView/style.module.scss
Normal file
@ -0,0 +1,16 @@
|
||||
.imageWrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%; /* Adjust as needed */
|
||||
height: 100%; /* Adjust as needed */
|
||||
overflow: hidden; /* Ensure no overflow */
|
||||
border: 1px solid #ccc; /* Optional: for visual debugging */
|
||||
background-color: #e0f7fa; /* Optional: for visual debugging */
|
||||
}
|
||||
|
||||
.image {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: contain; /* Ensure the image fits within the container */
|
||||
}
|
@ -62,6 +62,8 @@ import {
|
||||
import styles from './style.module.scss'
|
||||
import { PdfFile } from '../../types/drawing'
|
||||
import { DrawPDFFields } from '../../components/DrawPDFFields'
|
||||
import { Mark } from '../../types/mark.ts'
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
export const CreatePage = () => {
|
||||
const navigate = useNavigate()
|
||||
@ -339,34 +341,29 @@ export const CreatePage = () => {
|
||||
return fileHashes
|
||||
}
|
||||
|
||||
const createMarkConfig = (fileHashes: { [key: string]: string }) => {
|
||||
const markConfig: any = {}
|
||||
|
||||
drawnPdfs.forEach(drawnPdf => {
|
||||
const fileHash = fileHashes[drawnPdf.file.name]
|
||||
|
||||
drawnPdf.pages.forEach((page, pageIndex) => {
|
||||
page.drawnFields.forEach(drawnField => {
|
||||
if (!markConfig[drawnField.counterpart]) markConfig[drawnField.counterpart] = {}
|
||||
if (!markConfig[drawnField.counterpart][fileHash]) markConfig[drawnField.counterpart][fileHash] = []
|
||||
|
||||
console.log('drawn field: ', drawnField);
|
||||
|
||||
markConfig[drawnField.counterpart][fileHash].push({
|
||||
markType: drawnField.type,
|
||||
markLocation: {
|
||||
page: pageIndex,
|
||||
const createMarkConfig = (fileHashes: { [key: string]: string }) : Mark[] => {
|
||||
return drawnPdfs.flatMap((drawnPdf) => {
|
||||
const fileHash = fileHashes[drawnPdf.file.name];
|
||||
return drawnPdf.pages.flatMap((page, index) => {
|
||||
return page.drawnFields.map((drawnField) => {
|
||||
return {
|
||||
type: drawnField.type,
|
||||
location: {
|
||||
page: index,
|
||||
top: drawnField.top,
|
||||
left: drawnField.left,
|
||||
height: drawnField.height,
|
||||
width: drawnField.width,
|
||||
},
|
||||
npub: drawnField.counterpart,
|
||||
pdfFileHash: fileHash
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return markConfig
|
||||
.map((mark, index) => {
|
||||
return {...mark, id: index }
|
||||
});
|
||||
}
|
||||
|
||||
// Handle errors during zip file generation
|
||||
|
32
src/pages/sign/MarkFormField.tsx
Normal file
32
src/pages/sign/MarkFormField.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import { CurrentUserMark, Mark } from '../../types/mark.ts'
|
||||
import styles from './style.module.scss'
|
||||
import { Box, Button, TextField } from '@mui/material'
|
||||
|
||||
interface MarkFormFieldProps {
|
||||
handleSubmit: (event: any) => void
|
||||
handleChange: (event: any) => void
|
||||
currentMark: CurrentUserMark
|
||||
currentMarkValue: string
|
||||
}
|
||||
|
||||
const MarkFormField = (props: MarkFormFieldProps) => {
|
||||
const { handleSubmit, handleChange, currentMark, currentMarkValue } = props;
|
||||
const getSubmitButton = () => currentMark.isLast ? 'Complete' : 'Next';
|
||||
return (
|
||||
<div className={styles.fixedBottomForm}>
|
||||
<Box component="form" onSubmit={handleSubmit}>
|
||||
<TextField
|
||||
id="mark-value"
|
||||
label={currentMark.mark.type}
|
||||
value={currentMarkValue}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<Button type="submit" variant="contained">
|
||||
{getSubmitButton()}
|
||||
</Button>
|
||||
</Box>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default MarkFormField;
|
@ -1,8 +1,8 @@
|
||||
import { Box, Button, Typography } from '@mui/material'
|
||||
import { Box, Button, FormControl, InputLabel, TextField, Typography } from '@mui/material'
|
||||
import axios from 'axios'
|
||||
import saveAs from 'file-saver'
|
||||
import JSZip from 'jszip'
|
||||
import _ from 'lodash'
|
||||
import _, { set } from 'lodash'
|
||||
import { MuiFileInput } from 'mui-file-input'
|
||||
import { Event, verifyEvent } from 'nostr-tools'
|
||||
import { useEffect, useState } from 'react'
|
||||
@ -36,7 +36,8 @@ import styles from './style.module.scss'
|
||||
import { PdfFile } from '../../types/drawing.ts'
|
||||
import { toFile, toPdfFile } from '../../utils/pdf.ts'
|
||||
import PdfView from '../../components/PDFView'
|
||||
import { MarkConfig } from '../../types/mark.ts'
|
||||
import { CurrentUserMark, Mark, MarkConfig, MarkConfigDetails, User } from '../../types/mark.ts'
|
||||
import MarkFormField from './MarkFormField.tsx'
|
||||
enum SignedStatus {
|
||||
Fully_Signed,
|
||||
User_Is_Next_Signer,
|
||||
@ -74,7 +75,7 @@ export const SignPage = () => {
|
||||
|
||||
const [signers, setSigners] = useState<`npub1${string}`[]>([])
|
||||
const [viewers, setViewers] = useState<`npub1${string}`[]>([])
|
||||
const [markConfig, setMarkConfig] = useState<MarkConfig | null>(null)
|
||||
const [marks, setMarks] = useState<Mark[] >([])
|
||||
const [creatorFileHashes, setCreatorFileHashes] = useState<{
|
||||
[key: string]: string
|
||||
}>({})
|
||||
@ -93,6 +94,11 @@ export const SignPage = () => {
|
||||
|
||||
const [authUrl, setAuthUrl] = useState<string>()
|
||||
const nostrController = NostrController.getInstance()
|
||||
const [currentUserMark, setCurrentUserMark] = useState<CurrentUserMark | null>(null);
|
||||
const [currentUserMarks, setCurrentUserMarks] = useState<CurrentUserMark[]>([]);
|
||||
const [currentMarkValue, setCurrentMarkValue] = useState<string>('');
|
||||
const [isMarksCompleted, setIsMarksCompleted] = useState(false);
|
||||
const [isLastUserMark, setIsLastUserMark] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (signers.length > 0) {
|
||||
@ -183,9 +189,25 @@ export const SignPage = () => {
|
||||
setViewers(createSignatureContent.viewers)
|
||||
setCreatorFileHashes(createSignatureContent.fileHashes)
|
||||
setSubmittedBy(createSignatureEvent.pubkey)
|
||||
setMarkConfig(createSignatureContent.markConfig);
|
||||
setMarks(createSignatureContent.markConfig);
|
||||
|
||||
console.log('createSignatureContent', createSignatureContent)
|
||||
console.log('createSignatureContent markConfig', createSignatureContent);
|
||||
if (usersPubkey) {
|
||||
console.log('this runs behind users pubkey');
|
||||
const curMarks = getCurrentUserMarks(createSignatureContent.markConfig, usersPubkey)
|
||||
if (curMarks.length === 0) {
|
||||
setIsMarksCompleted(true)
|
||||
} else {
|
||||
const nextMark = findNextIncompleteMark(curMarks)
|
||||
if (!nextMark) {
|
||||
setIsMarksCompleted(true)
|
||||
} else {
|
||||
setCurrentUserMark(nextMark)
|
||||
setIsMarksCompleted(false)
|
||||
}
|
||||
setCurrentUserMarks(curMarks)
|
||||
}
|
||||
}
|
||||
|
||||
setSignedBy(Object.keys(meta.docSignatures) as `npub1${string}`[])
|
||||
}
|
||||
@ -514,6 +536,57 @@ export const SignPage = () => {
|
||||
)
|
||||
}
|
||||
|
||||
const handleMarkClick = (id: number) => {
|
||||
const nextMark = currentUserMarks.find(mark => mark.mark.id === id)
|
||||
setCurrentUserMark(nextMark!)
|
||||
setCurrentMarkValue(nextMark?.mark.value || "")
|
||||
}
|
||||
|
||||
const getMarkConfigPerUser = (markConfig: MarkConfig) => {
|
||||
if (!usersPubkey) return;
|
||||
return markConfig[hexToNpub(usersPubkey)];
|
||||
}
|
||||
|
||||
const handleChange = (event: any) => setCurrentMarkValue(event.target.value);
|
||||
|
||||
const handleSubmit = (event: any) => {
|
||||
event.preventDefault();
|
||||
if (!currentMarkValue || !currentUserMark) return;
|
||||
|
||||
const curMark = {
|
||||
...currentUserMark.mark,
|
||||
value: currentMarkValue
|
||||
};
|
||||
|
||||
const indexToUpdate = marks.findIndex(mark => mark.id === curMark.id);
|
||||
|
||||
const updatedMarks: Mark[] = [
|
||||
...marks.slice(0, indexToUpdate),
|
||||
curMark,
|
||||
...marks.slice(indexToUpdate + 1)
|
||||
];
|
||||
|
||||
setMarks(updatedMarks)
|
||||
setCurrentMarkValue("")
|
||||
|
||||
const updatedCurUserMarks = getCurrentUserMarks(updatedMarks, usersPubkey!)
|
||||
console.log('updatedCurUserMarks: ', updatedCurUserMarks)
|
||||
setCurrentUserMarks(updatedCurUserMarks)
|
||||
const nextMark = findNextIncompleteMark(updatedCurUserMarks)
|
||||
console.log('next mark: ', nextMark)
|
||||
if (!nextMark) {
|
||||
setCurrentUserMark(null)
|
||||
setIsMarksCompleted(true)
|
||||
} else {
|
||||
setCurrentUserMark(nextMark)
|
||||
setIsMarksCompleted(false)
|
||||
}
|
||||
}
|
||||
|
||||
const findNextIncompleteMark = (usersMarks: CurrentUserMark[]): CurrentUserMark | undefined => {
|
||||
return usersMarks.find(mark => !mark.isCompleted);
|
||||
}
|
||||
|
||||
// Update the meta signatures
|
||||
const updateMetaSignatures = (meta: Meta, signedEvent: SignedEvent): Meta => {
|
||||
const metaCopy = _.cloneDeep(meta)
|
||||
@ -735,6 +808,25 @@ export const SignPage = () => {
|
||||
navigate(appPublicRoutes.verify)
|
||||
}
|
||||
|
||||
const getCurrentUserMarks = (marks: Mark[], pubkey: string): CurrentUserMark[] => {
|
||||
console.log('marks: ', marks);
|
||||
|
||||
const filteredMarks = marks
|
||||
.filter(mark => mark.npub === hexToNpub(pubkey))
|
||||
const currentMarks = filteredMarks
|
||||
.map((mark, index, arr) => {
|
||||
return {
|
||||
mark,
|
||||
isLast: isLast(index, arr),
|
||||
isCompleted: !!mark.value
|
||||
}
|
||||
})
|
||||
console.log('current marks: ', currentMarks)
|
||||
return currentMarks;
|
||||
}
|
||||
|
||||
const isLast = (index: number, arr: any[]) => (index === (arr.length -1))
|
||||
|
||||
const handleExportSigit = async () => {
|
||||
if (Object.entries(files).length === 0 || !meta) return
|
||||
|
||||
@ -852,9 +944,12 @@ export const SignPage = () => {
|
||||
)
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return <LoadingSpinner desc={loadingSpinnerDesc} />
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
|
||||
<Box className={styles.container}>
|
||||
{displayInput && (
|
||||
<>
|
||||
@ -881,56 +976,68 @@ export const SignPage = () => {
|
||||
</>
|
||||
)}
|
||||
|
||||
{submittedBy && Object.entries(files).length > 0 && meta && (
|
||||
<>
|
||||
<DisplayMeta
|
||||
meta={meta}
|
||||
{/*{submittedBy && Object.entries(files).length > 0 && meta && (*/}
|
||||
{/* <>*/}
|
||||
{/* <DisplayMeta*/}
|
||||
{/* meta={meta}*/}
|
||||
{/* files={files}*/}
|
||||
{/* submittedBy={submittedBy}*/}
|
||||
{/* signers={signers}*/}
|
||||
{/* viewers={viewers}*/}
|
||||
{/* creatorFileHashes={creatorFileHashes}*/}
|
||||
{/* currentFileHashes={currentFileHashes}*/}
|
||||
{/* signedBy={signedBy}*/}
|
||||
{/* nextSigner={nextSinger}*/}
|
||||
{/* getPrevSignersSig={getPrevSignersSig}*/}
|
||||
{/* />*/}
|
||||
|
||||
{/* {signedStatus === SignedStatus.Fully_Signed && (*/}
|
||||
{/* <Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>*/}
|
||||
{/* <Button onClick={handleExport} variant="contained">*/}
|
||||
{/* Export*/}
|
||||
{/* </Button>*/}
|
||||
{/* </Box>*/}
|
||||
{/* )}*/}
|
||||
|
||||
{/* {signedStatus === SignedStatus.User_Is_Next_Signer && (*/}
|
||||
{/* <Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>*/}
|
||||
{/* <Button onClick={handleSign} variant="contained">*/}
|
||||
{/* Sign*/}
|
||||
{/* </Button>*/}
|
||||
{/* </Box>*/}
|
||||
{/* )}*/}
|
||||
|
||||
{/* {isSignerOrCreator && (*/}
|
||||
{/* <Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>*/}
|
||||
{/* <Button onClick={handleExportSigit} variant="contained">*/}
|
||||
{/* Export Sigit*/}
|
||||
{/* </Button>*/}
|
||||
{/* </Box>*/}
|
||||
{/* )}*/}
|
||||
{/* </>*/}
|
||||
{/*)}*/}
|
||||
{
|
||||
!isMarksCompleted && marks.length > 0 && (
|
||||
<PdfView
|
||||
files={files}
|
||||
submittedBy={submittedBy}
|
||||
signers={signers}
|
||||
viewers={viewers}
|
||||
creatorFileHashes={creatorFileHashes}
|
||||
currentFileHashes={currentFileHashes}
|
||||
signedBy={signedBy}
|
||||
nextSigner={nextSinger}
|
||||
getPrevSignersSig={getPrevSignersSig}
|
||||
marks={marks}
|
||||
fileHashes={currentFileHashes}
|
||||
handleMarkClick={handleMarkClick}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
{signedStatus === SignedStatus.Fully_Signed && (
|
||||
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
||||
<Button onClick={handleExport} variant="contained">
|
||||
Export
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
{
|
||||
!isMarksCompleted && currentUserMark !== null && <MarkFormField
|
||||
handleSubmit={handleSubmit}
|
||||
handleChange={handleChange}
|
||||
currentMark={currentUserMark}
|
||||
currentMarkValue={currentMarkValue}
|
||||
/>
|
||||
}
|
||||
|
||||
{signedStatus === SignedStatus.User_Is_Next_Signer && (
|
||||
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
||||
<Button onClick={handleSign} variant="contained">
|
||||
Sign
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
{ isMarksCompleted && <p>Ready to Sign!</p>}
|
||||
|
||||
{isSignerOrCreator && (
|
||||
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
||||
<Button onClick={handleExportSigit} variant="contained">
|
||||
Export Sigit
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{markConfig && (<PdfView
|
||||
files={files}
|
||||
markConfig={markConfig}
|
||||
fileHashes={currentFileHashes}/>)}
|
||||
|
||||
<div
|
||||
className={styles.fixedBottomForm}>
|
||||
<input type="text" placeholder="type here..." />
|
||||
<button>Next</button>
|
||||
</div>
|
||||
|
||||
</Box>
|
||||
</>
|
||||
|
@ -51,7 +51,10 @@
|
||||
.fixedBottomForm {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 50%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
border-top: 1px solid #ccc;
|
||||
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
|
||||
padding: 10px 20px;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { MarkConfig } from "./mark"
|
||||
import { Mark } from './mark'
|
||||
import { Keys } from '../store/auth/types'
|
||||
|
||||
export enum UserRole {
|
||||
@ -23,7 +23,7 @@ export interface CreateSignatureEventContent {
|
||||
signers: `npub1${string}`[]
|
||||
viewers: `npub1${string}`[]
|
||||
fileHashes: { [key: string]: string }
|
||||
markConfig: MarkConfig
|
||||
markConfig: Mark[]
|
||||
title: string
|
||||
zipUrl: string
|
||||
}
|
||||
|
@ -1,10 +1,25 @@
|
||||
import { MarkType } from "./drawing";
|
||||
|
||||
// export interface Mark {
|
||||
// /**
|
||||
// * @key png (pdf page) file hash
|
||||
// */
|
||||
// [key: string]: MarkConfigDetails[]
|
||||
// }
|
||||
|
||||
export interface CurrentUserMark {
|
||||
mark: Mark
|
||||
isLast: boolean
|
||||
isCompleted: boolean
|
||||
}
|
||||
|
||||
export interface Mark {
|
||||
/**
|
||||
* @key png (pdf page) file hash
|
||||
*/
|
||||
[key: string]: MarkConfigDetails[]
|
||||
id: number;
|
||||
npub: string;
|
||||
pdfFileHash: string;
|
||||
type: MarkType;
|
||||
location: MarkLocation;
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export interface MarkConfig {
|
||||
@ -33,11 +48,12 @@ export interface MarkValue {
|
||||
}
|
||||
|
||||
export interface MarkConfigDetails {
|
||||
markType: MarkType;
|
||||
type: MarkType;
|
||||
/**
|
||||
* Coordinates in format: X:10;Y:50
|
||||
*/
|
||||
markLocation: MarkLocation;
|
||||
location: MarkLocation;
|
||||
value?: MarkValue
|
||||
}
|
||||
|
||||
export interface MarkLocation {
|
||||
|
Loading…
Reference in New Issue
Block a user