sigit.io/src/pages/home/index.tsx

218 lines
6.3 KiB
TypeScript
Raw Normal View History

import { Button, Divider, TextField, Tooltip } from '@mui/material'
2024-06-28 14:24:14 +05:00
import JSZip from 'jszip'
import { useEffect, useRef, useState } from 'react'
2024-05-14 14:27:05 +05:00
import { useNavigate } from 'react-router-dom'
2024-06-28 14:24:14 +05:00
import { toast } from 'react-toastify'
2024-07-05 13:38:04 +05:00
import { useAppSelector } from '../../hooks'
import { appPrivateRoutes, appPublicRoutes } from '../../routes'
import { Meta, ProfileMetadata } from '../../types'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
2024-06-28 14:24:14 +05:00
import {
faAdd,
faFilter,
faFilterCircleXmark,
faSearch
} from '@fortawesome/free-solid-svg-icons'
import { Select } from '../../components/Select'
import { DisplaySigit } from '../../components/DisplaySigit'
import { Container } from '../../components/Container'
import styles from './style.module.scss'
// 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 = () => {
2024-05-14 14:27:05 +05:00
const navigate = useNavigate()
const fileInputRef = useRef<HTMLInputElement>(null)
2024-07-05 13:38:04 +05:00
const [sigits, setSigits] = useState<Meta[]>([])
2024-06-28 14:24:14 +05:00
const [profiles, setProfiles] = useState<{ [key: string]: ProfileMetadata }>(
{}
)
2024-07-05 13:38:04 +05:00
const usersAppData = useAppSelector((state) => state.userAppData)
2024-06-28 14:24:14 +05:00
useEffect(() => {
2024-07-05 13:38:04 +05:00
if (usersAppData) {
setSigits(Object.values(usersAppData.sigits))
}
}, [usersAppData])
const handleUploadClick = () => {
if (fileInputRef.current) {
fileInputRef.current.click()
}
}
const handleFileChange = async (
event: React.ChangeEvent<HTMLInputElement>
) => {
const file = event.target.files?.[0]
if (file) {
// 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 zip file')
return
}
// navigate to create page
navigate(appPrivateRoutes.create, { state: { uploadedFile: file } })
}
}
const [filter, setFilter] = useState<Filter>('Show all')
const [isFilterVisible, setIsFilterVisible] = useState(true)
const [sort, setSort] = useState<Sort>('asc')
return (
<Container className={styles.container}>
<div className={styles.header}>
{isFilterVisible && (
<>
<Select
setValue={setFilter}
options={FILTERS.map((f) => {
return {
label: f,
value: f
}
})}
/>
<Select
setValue={setSort}
options={SORT_BY.map((s) => {
return { ...s }
})}
/>
</>
)}
<div className={styles.actionButtons}>
<div className={styles.search}>
<TextField
placeholder="Search"
size="small"
sx={{
fontSize: '16px',
height: '34px',
borderTopLeftRadius: 'var(----mui-shape-borderRadius)',
borderBottomLeftRadius: 'var(----mui-shape-borderRadius)',
'& .MuiInputBase-root': {
borderTopRightRadius: 0,
borderBottomRightRadius: 0
},
'& .MuiInputBase-input': {
padding: '5.5px 14px'
},
'& .MuiOutlinedInput-notchedOutline': {
display: 'none'
}
}}
/>
<Button
sx={{
minWidth: '44px',
padding: '10px 12px',
borderTopLeftRadius: 0,
borderBottomLeftRadius: 0
}}
variant={'contained'}
>
<FontAwesomeIcon icon={faSearch} />
</Button>
</div>
<Divider orientation="vertical" variant="middle" flexItem />
<Tooltip title="Toggle Filter" arrow>
<Button
sx={{
minWidth: '44px',
padding: '10px 12px'
}}
variant={'contained'}
onClick={() => setIsFilterVisible((v) => !v)}
>
{isFilterVisible ? (
<FontAwesomeIcon icon={faFilterCircleXmark} />
) : (
<FontAwesomeIcon icon={faFilter} />
)}
</Button>
</Tooltip>
<Tooltip title="Upload" arrow>
<Button
sx={{
minWidth: '44px',
padding: '10px 12px'
}}
component={'label'}
htmlFor="fileUpload"
variant={'contained'}
onClick={handleUploadClick}
>
<FontAwesomeIcon icon={faAdd} />
</Button>
</Tooltip>
<input
id="fileUpload"
type="file"
hidden
ref={fileInputRef}
onChange={handleFileChange}
/>
</div>
</div>
<div className={styles.dropzone}>
<div>Click or drag files to upload!</div>
</div>
<div className={styles.submissions}>
{sigits.map((sigit, index) => (
<DisplaySigit
key={`sigit-${index}`}
meta={sigit}
profiles={profiles}
setProfiles={setProfiles}
/>
))}
</div>
</Container>
2024-06-07 16:13:32 +05:00
)
}