import { Button, TextField } from '@mui/material' import JSZip from 'jszip' import { useCallback, useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import { toast } from 'react-toastify' import { useAppSelector } from '../../hooks' import { appPrivateRoutes, appPublicRoutes } from '../../routes' import { Meta, ProfileMetadata } from '../../types' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faSearch } from '@fortawesome/free-solid-svg-icons' import { Select } from '../../components/Select' import { DisplaySigit } from '../../components/DisplaySigit' import { useDropzone } from 'react-dropzone' import { Container } from '../../components/Container' import styles from './style.module.scss' import { extractSigitInfo, SigitInfo, SignedStatus } from '../../hooks/useSigitMeta' // Unsupported Filter options are commented const FILTERS = [ 'Show all', // 'Drafts', 'In-progress', 'Completed' // 'Archived' ] as const type Filter = (typeof FILTERS)[number] const SORT_BY = [ { label: 'Newest', value: 'desc' }, { label: 'Oldest', value: 'asc' } ] as const type Sort = (typeof SORT_BY)[number]['value'] export const HomePage = () => { const navigate = useNavigate() const [sigits, setSigits] = useState<{ [key: string]: Meta }>({}) const [parsedSigits, setParsedSigits] = useState<{ [key: string]: SigitInfo }>({}) const [profiles, setProfiles] = useState<{ [key: string]: ProfileMetadata }>( {} ) const usersAppData = useAppSelector((state) => state.userAppData) useEffect(() => { if (usersAppData) { const getSigitInfo = async () => { for (const key in usersAppData.sigits) { if (Object.prototype.hasOwnProperty.call(usersAppData.sigits, key)) { const sigitInfo = await extractSigitInfo(usersAppData.sigits[key]) if (sigitInfo) { setParsedSigits((prev) => { return { ...prev, [key]: sigitInfo } }) } } } } setSigits(usersAppData.sigits) getSigitInfo() } }, [usersAppData]) const onDrop = useCallback( async (acceptedFiles: File[]) => { // When uploading single file check if it's .sigit.zip if (acceptedFiles.length === 1) { const file = acceptedFiles[0] // Check if the file extension is .sigit.zip const fileName = file.name const fileExtension = fileName.slice(-10) // ".sigit.zip" has 10 characters if (fileExtension === '.sigit.zip') { const zip = await JSZip.loadAsync(file).catch((err) => { console.log('err in loading zip file :>> ', err) toast.error(err.message || 'An error occurred in loading zip file.') return null }) if (!zip) return // navigate to sign page if zip contains keys.json if ('keys.json' in zip.files) { return navigate(appPrivateRoutes.sign, { state: { uploadedZip: file } }) } // navigate to verify page if zip contains meta.json if ('meta.json' in zip.files) { return navigate(appPublicRoutes.verify, { state: { uploadedZip: file } }) } toast.error('Invalid SiGit zip file') return } } // navigate to create page navigate(appPrivateRoutes.create, { state: { uploadedFiles: acceptedFiles } }) }, [navigate] ) const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop }) const [search, setSearch] = useState('') const [filter, setFilter] = useState('Show all') const [sort, setSort] = useState('desc') return (
{ return { ...s } })} />
{ e.preventDefault() const searchInput = e.currentTarget.elements.namedItem( 'q' ) as HTMLInputElement setSearch(searchInput.value) }} > { // Handle the case when users click native search input's clear or x if (e.currentTarget.value === '') { setSearch(e.currentTarget.value) } }} sx={{ width: '100%', fontSize: '16px', borderTopLeftRadius: 'var(----mui-shape-borderRadius)', borderBottomLeftRadius: 'var(----mui-shape-borderRadius)', '& .MuiInputBase-root': { borderTopRightRadius: 0, borderBottomRightRadius: 0 }, '& .MuiInputBase-input': { padding: '7px 14px' }, '& .MuiOutlinedInput-notchedOutline': { display: 'none' } }} />
{isDragActive ? (

Drop the files here ...

) : (

Click or drag files to upload!

)}
{Object.keys(parsedSigits) .filter((s) => { const { title, signedStatus } = parsedSigits[s] const isMatch = title?.toLowerCase().includes(search.toLowerCase()) switch (filter) { case 'Completed': return signedStatus === SignedStatus.Complete && isMatch case 'In-progress': return signedStatus === SignedStatus.Partial && isMatch case 'Show all': return isMatch default: console.error('Filter case not handled.') } }) .sort((a, b) => { const x = parsedSigits[a].createdAt ?? 0 const y = parsedSigits[b].createdAt ?? 0 return sort === 'desc' ? y - x : x - y }) .map((key) => ( ))}
) }