Compare commits
7 commits
4119ee870e
...
66ff214024
| Author | SHA1 | Date | |
|---|---|---|---|
| 66ff214024 | |||
| 5f7cf1f49f | |||
| 2510353fbf | |||
| 03dd6ac4ad | |||
| 7228f82ed1 | |||
| f4af10e82a | |||
| db4b1c1065 |
9 changed files with 140 additions and 71 deletions
|
|
@ -12,7 +12,6 @@
|
|||
"@kobalte/core": "^0.13.11",
|
||||
"@solidjs-use/integrations": "^2.3.0",
|
||||
"@solidjs/router": "^0.15.3",
|
||||
"bcryptjs": "^3.0.2",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.18",
|
||||
"gsap": "^3.13.0",
|
||||
|
|
@ -24,6 +23,7 @@
|
|||
"solidjs-use": "^2.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nanostores/solid": "^1.1.1",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"sass-embedded": "^1.93.2",
|
||||
"typescript": "~5.8.3",
|
||||
|
|
|
|||
23
pnpm-lock.yaml
generated
23
pnpm-lock.yaml
generated
|
|
@ -17,9 +17,6 @@ importers:
|
|||
'@solidjs/router':
|
||||
specifier: ^0.15.3
|
||||
version: 0.15.3(solid-js@1.9.9)
|
||||
bcryptjs:
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2
|
||||
crypto-js:
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0
|
||||
|
|
@ -48,6 +45,9 @@ importers:
|
|||
specifier: ^2.3.0
|
||||
version: 2.3.0
|
||||
devDependencies:
|
||||
'@nanostores/solid':
|
||||
specifier: ^1.1.1
|
||||
version: 1.1.1(nanostores@1.0.1)(solid-js@1.9.9)
|
||||
'@types/crypto-js':
|
||||
specifier: ^4.2.2
|
||||
version: 4.2.2
|
||||
|
|
@ -481,6 +481,12 @@ packages:
|
|||
peerDependencies:
|
||||
solid-js: ^1.8.8
|
||||
|
||||
'@nanostores/solid@1.1.1':
|
||||
resolution: {integrity: sha512-gF0Eat1/c3hOaklBMSVoEjcNzJc5zGk4VSg94H9LPmXYww1pxgr7zylpi3jjyxRu24c8+aYNkmRWzolAwzSA1A==}
|
||||
peerDependencies:
|
||||
nanostores: '>=0.9.0 <2.0.0'
|
||||
solid-js: ^1.6.0
|
||||
|
||||
'@parcel/watcher-android-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
|
|
@ -828,10 +834,6 @@ packages:
|
|||
resolution: {integrity: sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==}
|
||||
hasBin: true
|
||||
|
||||
bcryptjs@3.0.2:
|
||||
resolution: {integrity: sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==}
|
||||
hasBin: true
|
||||
|
||||
braces@3.0.3:
|
||||
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
|
||||
engines: {node: '>=8'}
|
||||
|
|
@ -1759,6 +1761,11 @@ snapshots:
|
|||
'@solid-primitives/utils': 6.3.2(solid-js@1.9.9)
|
||||
solid-js: 1.9.9
|
||||
|
||||
'@nanostores/solid@1.1.1(nanostores@1.0.1)(solid-js@1.9.9)':
|
||||
dependencies:
|
||||
nanostores: 1.0.1
|
||||
solid-js: 1.9.9
|
||||
|
||||
'@parcel/watcher-android-arm64@2.5.1':
|
||||
optional: true
|
||||
|
||||
|
|
@ -2019,8 +2026,6 @@ snapshots:
|
|||
|
||||
baseline-browser-mapping@2.8.6: {}
|
||||
|
||||
bcryptjs@3.0.2: {}
|
||||
|
||||
braces@3.0.3:
|
||||
dependencies:
|
||||
fill-range: 7.1.1
|
||||
|
|
|
|||
|
|
@ -1,11 +1,20 @@
|
|||
import './File.sass'
|
||||
import { FileField } from '@kobalte/core/file-field'
|
||||
|
||||
export default () => {
|
||||
interface Props {
|
||||
maxFiles: number
|
||||
accept: string
|
||||
onFileAccept?: (files: File[]) => void
|
||||
label: string
|
||||
buttonText: string
|
||||
onClick: () => void
|
||||
}
|
||||
|
||||
export default (props: Props) => {
|
||||
return (
|
||||
<>
|
||||
<FileField class="filefield" maxFiles={1} onFileAccept={(data) => console.log('data', data)} onFileReject={(data) => console.log('data', data)} onFileChange={(data) => console.log('data', data)}>
|
||||
<FileField.Dropzone class="filefield__dropzone">Drag and drop or click to upload file</FileField.Dropzone>
|
||||
<FileField class="filefield" maxFiles={props.maxFiles} onFileAccept={props.onFileAccept} accept={props.accept}>
|
||||
<FileField.Dropzone class="filefield__dropzone">{props.label}</FileField.Dropzone>
|
||||
<FileField.HiddenInput />
|
||||
<FileField.ItemList class="filefield__itemList">
|
||||
{() => (
|
||||
|
|
@ -13,7 +22,9 @@ export default () => {
|
|||
<FileField.ItemPreviewImage class="filefield__itemPreviewImage" />
|
||||
<FileField.ItemName class="filefield__itemName" />
|
||||
<FileField.ItemSize class="filefield__itemSize" />
|
||||
<FileField.ItemDeleteTrigger class="filefield__itemDeleteTrigger">Delete</FileField.ItemDeleteTrigger>
|
||||
<FileField.ItemDeleteTrigger class="filefield__itemDeleteTrigger" onClick={props.onClick}>
|
||||
{props.buttonText}
|
||||
</FileField.ItemDeleteTrigger>
|
||||
</FileField.Item>
|
||||
)}
|
||||
</FileField.ItemList>
|
||||
|
|
|
|||
|
|
@ -1,52 +1,30 @@
|
|||
import './Modal.sass'
|
||||
import { type JSXElement, Show } from 'solid-js'
|
||||
import gsap from 'gsap'
|
||||
|
||||
interface Props {
|
||||
children: JSXElement
|
||||
background?: string
|
||||
color?: string
|
||||
border?: string
|
||||
trigger: boolean
|
||||
opacity?: number
|
||||
}
|
||||
|
||||
export default (props: Props) => {
|
||||
let dialogRef!: HTMLDivElement
|
||||
|
||||
// const openHandler = () => {
|
||||
// gsap.to(dialogRef, {
|
||||
// duration: 0,
|
||||
// display: 'flex',
|
||||
// ease: 'power2.out',
|
||||
// })
|
||||
// }
|
||||
|
||||
const closeHandler = () => {
|
||||
gsap.to(dialogRef, {
|
||||
duration: 0,
|
||||
display: 'none',
|
||||
ease: 'power2.out',
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Show when={props.trigger}>
|
||||
<div class="modal" ref={dialogRef} onClick={closeHandler}>
|
||||
<Show when={props.border}>
|
||||
<div class="modal__content" style={`background-color: ${props.background}; color: ${props.color}; border: 2px solid ${props.border}; opacity: ${props.opacity || 1}`}>
|
||||
{props.children}
|
||||
</div>
|
||||
</Show>
|
||||
<div class="modal">
|
||||
<Show when={props.border}>
|
||||
<div class="modal__content" style={`background-color: ${props.background}; color: ${props.color}; border: 2px solid ${props.border}; opacity: ${props.opacity || 1}`}>
|
||||
{props.children}
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<Show when={!props.border}>
|
||||
<div class="modal__content" style={`background-color: ${props.background}; color: ${props.color}; opacity: ${props.opacity || 1}; box-shadow: 5px 4px 6px rgba(0, 0, 0, 0.5)`}>
|
||||
{props.children}
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
</Show>
|
||||
<Show when={!props.border}>
|
||||
<div class="modal__content" style={`background-color: ${props.background}; color: ${props.color}; opacity: ${props.opacity || 1}; box-shadow: 5px 4px 6px rgba(0, 0, 0, 0.5)`}>
|
||||
{props.children}
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
51
src/components/Modal/ModalButton.tsx
Normal file
51
src/components/Modal/ModalButton.tsx
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import './Modal.sass'
|
||||
import { type JSXElement, Show, createSignal } from 'solid-js'
|
||||
import Button from '../Button/Button'
|
||||
|
||||
interface Props {
|
||||
children: JSXElement
|
||||
background?: string
|
||||
color?: string
|
||||
border?: string
|
||||
opacity?: number
|
||||
label: string
|
||||
edges?: 'curved' | 'rounded' | 'flat'
|
||||
design?: 'bu-primary' | 'bu-link' | 'bu-info' | 'bu-success' | 'bu-warning' | 'bu-danger' | 'bu-dark' | 'bu-light' | 'bu-text' | 'bu-ghost' | 'bo-primary' | 'bo-secondary' | 'bo-success' | 'bo-danger' | 'bo-warning' | 'bo-info' | 'bo-light' | 'bo-dark' | 'bo-link'
|
||||
width?: number
|
||||
wide?: boolean
|
||||
}
|
||||
|
||||
export default (props: Props) => {
|
||||
const [isOpen, setIsOpen] = createSignal(false)
|
||||
|
||||
const openHandler = () => {
|
||||
setIsOpen(true)
|
||||
}
|
||||
|
||||
const closeHandler = () => {
|
||||
setIsOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Show when={!isOpen()}>
|
||||
<Button label={props.label} edges={props.edges} design={props.design} onClick={openHandler} />
|
||||
</Show>
|
||||
<Show when={isOpen()}>
|
||||
<div class="modal" onClick={closeHandler}>
|
||||
<Show when={props.border}>
|
||||
<div class="modal__content" style={`background-color: ${props.background}; color: ${props.color}; border: 2px solid ${props.border}; opacity: ${props.opacity || 1}`}>
|
||||
{props.children}
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<Show when={!props.border}>
|
||||
<div class="modal__content" style={`background-color: ${props.background}; color: ${props.color}; opacity: ${props.opacity || 1}; box-shadow: 5px 4px 6px rgba(0, 0, 0, 0.5)`}>
|
||||
{props.children}
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
</Show>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ export { default as Row } from './Row/Row'
|
|||
export { default as Display } from './Display/Display'
|
||||
export { default as Padding } from './Padding/Padding'
|
||||
export { default as Modal } from './Modal/Modal'
|
||||
export { default as ModalButton } from './Modal/ModalButton'
|
||||
export { default as Table } from './Table/Table'
|
||||
export { default as Combobox } from './Combobox/Combobox'
|
||||
export { default as File } from './File/File'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,16 @@
|
|||
@use 'sass:color'
|
||||
|
||||
.box-title
|
||||
font-size: 1.75rem
|
||||
font-weight: 700
|
||||
|
||||
.approver-name
|
||||
font-size: 1.25rem
|
||||
font-size: 1.25rem
|
||||
|
||||
.required
|
||||
padding: 1rem
|
||||
border-radius: 8px
|
||||
background-color: color.adjust(#0D64E4, $blackness: 20%)
|
||||
opacity: 0.6
|
||||
width: 100%
|
||||
text-align: center
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import './Login.sass'
|
||||
import { Logo, Link, Page, Row, Padding, Form, Box, Radio, Combobox, Input, Button, Modal } from '../../components'
|
||||
import { Logo, Link, Page, Row, Padding, Box, Radio, Combobox, Input, Button } from '../../components'
|
||||
import { IoChevronBack } from 'solid-icons/io'
|
||||
import { createSignal, Show } from 'solid-js'
|
||||
import { createSignal, Show, createEffect } from 'solid-js'
|
||||
import { ofetch } from 'ofetch'
|
||||
import { SHA1, SHA3 } from 'crypto-js'
|
||||
import { useNavigate } from '@solidjs/router'
|
||||
|
|
@ -9,13 +9,12 @@ import { useNavigate } from '@solidjs/router'
|
|||
export default () => {
|
||||
const API = import.meta.env.VITE_BACKEND
|
||||
const APPROVERNAME = import.meta.env.VITE_HEAD
|
||||
const assessors = JSON.parse(sessionStorage.getItem('assessors')!)
|
||||
const assessors = JSON.parse(sessionStorage.getItem('registered')!)
|
||||
const roles = ['Assessor', 'Approver']
|
||||
|
||||
const [role, setRole] = createSignal('')
|
||||
const [role, setRole] = createSignal('Assessor')
|
||||
const [name, setName] = createSignal('')
|
||||
const [password, setPassword] = createSignal('')
|
||||
const [matched, setMatched] = createSignal(false)
|
||||
|
||||
const navigate = useNavigate()
|
||||
|
||||
|
|
@ -24,13 +23,8 @@ export default () => {
|
|||
const dbpassword = await ofetch(API + 'get-password/' + employeeid.result, { parseResponse: JSON.parse })
|
||||
const hashPassword = await securePassword()
|
||||
|
||||
console.log('dbpassword', dbpassword.result)
|
||||
console.log('hashPassword', hashPassword)
|
||||
console.log(dbpassword.result === hashPassword)
|
||||
|
||||
if (dbpassword.result === hashPassword) {
|
||||
setMatched(true)
|
||||
navigate('/')
|
||||
navigate('/notification')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -42,6 +36,11 @@ export default () => {
|
|||
return thirdHashing.toString()
|
||||
}
|
||||
|
||||
createEffect(() => {
|
||||
if (role() === 'Approver') setName(APPROVERNAME)
|
||||
else if (role() !== 'Approver' && name() === APPROVERNAME) setName('')
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<Page alignment="column">
|
||||
|
|
@ -65,7 +64,14 @@ export default () => {
|
|||
<Row>
|
||||
<Box curved thickness={2} padding={2} color="#2f465cd7" background="#04040642">
|
||||
<Row>
|
||||
<span class="box-title">Login</span>
|
||||
<span
|
||||
class="box-title"
|
||||
onClick={() => {
|
||||
console.log(name())
|
||||
}}
|
||||
>
|
||||
Login
|
||||
</span>
|
||||
</Row>
|
||||
|
||||
<Padding top={2} left={2} right={2} bottom={0}>
|
||||
|
|
@ -84,18 +90,28 @@ export default () => {
|
|||
<Input value={password()} onChange={setPassword}></Input>
|
||||
|
||||
<Padding top={2} left={0} right={0} bottom={0}>
|
||||
<Row>
|
||||
<Button edges="curved" design="bo-primary" label="Login" wide onClick={login}></Button>
|
||||
</Row>
|
||||
<Show when={password() && name()}>
|
||||
<Row>
|
||||
<Button edges="curved" design="bo-primary" label="Login" wide onClick={login}></Button>
|
||||
</Row>
|
||||
</Show>
|
||||
|
||||
<Show when={!password() && name()}>
|
||||
<Row>
|
||||
<span class="required">Required password</span>
|
||||
</Row>
|
||||
</Show>
|
||||
|
||||
<Show when={!password() && !name()}>
|
||||
<Row>
|
||||
<span class="required">Required name and password</span>
|
||||
</Row>
|
||||
</Show>
|
||||
</Padding>
|
||||
</Box>
|
||||
</Row>
|
||||
</Padding>
|
||||
</Page>
|
||||
|
||||
<Modal trigger={matched()} background="#ffffffff" color="#000000e4" opacity={0.5}>
|
||||
<h1>1</h1>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import { ofetch } from 'ofetch'
|
|||
import { SHA3, SHA1 } from 'crypto-js'
|
||||
import dayjs from 'dayjs'
|
||||
import { FileField } from '@kobalte/core/file-field'
|
||||
import bcrypt from 'bcryptjs'
|
||||
|
||||
export default () => {
|
||||
const API = import.meta.env.VITE_BACKEND
|
||||
|
|
@ -71,8 +70,6 @@ export default () => {
|
|||
}
|
||||
|
||||
const securePassword = async () => {
|
||||
// const salt = bcrypt.genSaltSync(9)
|
||||
// const hash = bcrypt.hashSync(password(), salt)
|
||||
const firstHashing = SHA1(password())
|
||||
const secondHashing = SHA3(firstHashing)
|
||||
const thirdHashing = SHA1(secondHashing)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue