Compare commits

...

3 commits

Author SHA1 Message Date
52ebeebe4d Updated register page 2025-09-26 17:33:42 +08:00
640f02470f Updated login page 2025-09-26 17:33:32 +08:00
64d4e90d70 Added radio component 2025-09-26 17:33:06 +08:00
7 changed files with 206 additions and 38 deletions

View file

@ -0,0 +1,62 @@
.radio-group
display: flex
flex-direction: column
gap: 8px
&__label
color: hsl(240 6% 10%)
font-size: 14px
font-weight: 500
user-select: none
&__description
color: hsl(240 5% 26%)
font-size: 12px
user-select: none
&__error-message
color: hsl(0 72% 51%)
font-size: 12px
user-select: none
&__items
display: flex
.radio
display: flex
align-items: center
&__control
display: flex
align-items: center
justify-content: center
height: 20px
width: 20px
border-radius: 10px
border: 1px solid hsl(240 5% 84%)
background-color: hsl(240 6% 90%)
// margin: 2rem
&__input:focus-visible + &__control
outline: 2px solid #33475a
outline-offset: 2px
&__control[data-checked]
border-color: #33475a
background-color: #577693
&__control[data-checked][data-invalid]
border-color: #33475a
background-color: hsl(0 72% 51%)
&__indicator
height: 10px
width: 10px
border-radius: 5px
background-color: white
&__label
margin-left: 8px
color: #ffffff
font-size: 1rem
user-select: none

View file

@ -0,0 +1,36 @@
import './Radio.sass'
import { RadioGroup } from '@kobalte/core/radio-group'
import { type Setter, For, Show } from 'solid-js'
interface Props {
label?: string
data: string[]
value: string
onChange: Setter<string>
gap?: number
}
export default (props: Props) => {
return (
<>
<RadioGroup class="radio-group" value={props.value} onChange={props.onChange}>
<Show when={props.label}>
<RadioGroup.Label class="radio-group__label">{props.label}</RadioGroup.Label>
</Show>
<div class="radio-group__items" role="presentation" style={`gap: ${props.gap || 1}rem`}>
<For each={props.data}>
{(item) => (
<RadioGroup.Item value={item} class="radio">
<RadioGroup.ItemInput class="radio__input" />
<RadioGroup.ItemControl class="radio__control">
<RadioGroup.ItemIndicator class="radio__indicator" />
</RadioGroup.ItemControl>
<RadioGroup.ItemLabel class="radio__label">{item}</RadioGroup.ItemLabel>
</RadioGroup.Item>
)}
</For>
</div>
</RadioGroup>
</>
)
}

View file

@ -19,6 +19,7 @@ export { default as Combobox } from './Combobox/Combobox'
export { default as File } from './File/File'
export { default as QR } from './QR/QR'
export { default as Input } from './Input/Input'
export { default as Radio } from './Radio/Radio'
// export { default as OptimizeBackground } from './Optimizers/OptimizeBackground'
// export { default as OptimizeImage } from './Optimizers/OptimizeImage'
// export { default as OptimizeLogo } from './Optimizers/OptimizeLogo'

View file

@ -0,0 +1,6 @@
.box-title
font-size: 1.75rem
font-weight: 700
.approver-name
font-size: 1.25rem

View file

@ -1,42 +1,101 @@
import './Login.sass'
import { Logo, Link, Page, Row, Padding, Form, Box } from '../../components'
import { Logo, Link, Page, Row, Padding, Form, Box, Radio, Combobox, Input, Button, Modal } from '../../components'
import { IoChevronBack } from 'solid-icons/io'
import { createSignal, Show } from 'solid-js'
import { ofetch } from 'ofetch'
import { SHA1, SHA3 } from 'crypto-js'
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 roles = ['Assessor', 'Approver']
const [role, setRole] = createSignal('')
const [name, setName] = createSignal('')
const [password, setPassword] = createSignal('')
const [matched, setMatched] = createSignal(false)
const navigate = useNavigate()
const login = async () => {
const employeeid = await ofetch(API + 'get-employeeid/' + name(), { parseResponse: JSON.parse })
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('/')
}
}
const securePassword = async () => {
const firstHashing = SHA1(password())
const secondHashing = SHA3(firstHashing)
const thirdHashing = SHA1(secondHashing)
return thirdHashing.toString()
}
return (
<>
<Page alignment="column">
<Padding left={4.75} right={4.75} top={0} bottom={0}>
<Row content="split">
<Link to="/">
<Row content="left" gap={2}>
<Logo size={200} />
<h1>OCBO e-Sign</h1>
</Row>
</Link>
<Link to="/">
<Row content="right">
<IoChevronBack size={45} />
<span class="back-button-text">Back</span>
</Row>
</Link>
</Row>
<Padding top={2} left={0} right={0} bottom={0}>
<Row>
<Box curved thickness={2} padding={2} color="#2f465cd7">
<Row>
<span class="box-title">Login</span>
</Row>
<Form>
<h4>Role</h4>
</Form>
</Box>
<Row content="split">
<Link to="/">
<Row content="left" gap={2}>
<Logo size={200} />
<h1>OCBO e-Sign</h1>
</Row>
</Padding>
</Link>
<Link to="/">
<Row content="right">
<IoChevronBack size={45} />
<span class="back-button-text">Back</span>
</Row>
</Link>
</Row>
<Padding top={2} left={0} right={0} bottom={0}>
<Row>
<Box curved thickness={2} padding={2} color="#2f465cd7" background="#04040642">
<Row>
<span class="box-title">Login</span>
</Row>
<Padding top={2} left={2} right={2} bottom={0}>
<Row>
<Radio data={roles} value={role()} onChange={setRole} gap={10} />
</Row>
</Padding>
<h4>Name</h4>
<Show when={role() !== 'Approver'}>
<Combobox options={assessors} placeholder="Select your name" value={name()} onChange={setName} />
</Show>
<Show when={role() === 'Approver'}>
<span class="approver-name">{APPROVERNAME}</span>
</Show>
<h4>Password</h4>
<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>
</Padding>
</Box>
</Row>
</Padding>
</Page>
<Modal trigger={matched()} background="#ffffffff" color="#000000e4" opacity={0.5}>
<h1>1</h1>
</Modal>
</>
)
}

View file

@ -26,6 +26,8 @@
border-radius: 8px
background-color: color.adjust(#0D64E4, $blackness: 20%)
opacity: 0.6
width: 100%
text-align: center
.filefield
display: flex

View file

@ -10,7 +10,7 @@ import bcrypt from 'bcryptjs'
export default () => {
const API = import.meta.env.VITE_BACKEND
const APPROVERNAME = 'ARCH. KHASHAYAR L. TOGHYANI'
const APPROVERNAME = import.meta.env.VITE_HEAD
const assessors = JSON.parse(sessionStorage.getItem('assessors')!)
const roles = ['ASSESSOR', 'APPROVER']
@ -71,10 +71,12 @@ export default () => {
}
const securePassword = async () => {
const salt = bcrypt.genSaltSync(9)
const hash = bcrypt.hashSync(password(), salt)
const sha = SHA1(hash)
setHashPassword(sha.toString())
// const salt = bcrypt.genSaltSync(9)
// const hash = bcrypt.hashSync(password(), salt)
const firstHashing = SHA1(password())
const secondHashing = SHA3(firstHashing)
const thirdHashing = SHA1(secondHashing)
setHashPassword(thirdHashing.toString())
}
const convertBase64 = (blob: Blob) => {
@ -137,7 +139,7 @@ export default () => {
<Padding top={2} left={0} right={0} bottom={0}>
<Row>
<Box curved thickness={2} padding={2} color="#2f465cd7">
<Box curved thickness={2} padding={2} color="#2f465cd7" background="#04040642">
<Row>
<span class="box-title">Registration</span>
</Row>
@ -171,7 +173,7 @@ export default () => {
<Padding top={2} bottom={0} left={0} right={0}>
<Row>
<Button edges="curved" design="bo-primary" label="Register" onClick={generateSignature} />
<Button edges="curved" design="bo-primary" label="Register" onClick={generateSignature} wide />
</Row>
</Padding>
</Show>
@ -210,7 +212,7 @@ export default () => {
<Padding top={2} bottom={0} left={0} right={0}>
<Row>
<Button edges="curved" design="bo-primary" label="Register" onClick={generateSignature} />
<Button edges="curved" design="bo-primary" label="Register" onClick={generateSignature} wide />
</Row>
</Padding>
</Show>
@ -229,7 +231,7 @@ export default () => {
</Padding>
</Page>
<Modal trigger={saved()} background="#ffffffff" color="#000000e4" opacity={0.4}>
<Modal trigger={saved()} background="#ffffffff" color="#000000e4" opacity={0.6}>
<Padding top={1} bottom={1} left={4} right={4}>
<Column>
<Row>