Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions src/app/(app)/evaluation/fail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
'use client'

import Image from 'next/image'
import Link from 'next/link'

import { config } from '@/app/config'
import { Button } from '@/components/ui/button'

const EvaluationFail: React.FC = () => {
const goBack = (): void => {
console.log('Go Back')
}

return (
<div className='flex flex-col justify-center bg-white font-mitr'>
{/* Header */}
<div className='flex flex-col items-center justify-center gap-4 py-6'>
{/* Text */}
<div className='flex flex-col items-center text-[#064E41]'>
<div className='text-xl font-medium'>แบบประเมิน</div>
<div className='text-xl font-medium'>Chula Open House 2025</div>
</div>

{/* Logo */}
<object
className='h-[220px] w-[220px]'
data={`${config.cdnURL}/assets/register/oph-logo.svg`}
type='image/svg+xml'
>
<Image
alt='logo'
height={220}
src={`${config.cdnURL}/assets/register/oph-logo.svg`}
width={220}
/>
</object>
</div>

{/* Content */}
<div className='flex flex-col items-center justify-center bg-white pb-6'>
<p className='text-center text-base font-light text-[#F00]'>
ขออภัย<b>ท่านไม่มีสิทธิ์ทำแบบประเมิน</b>และ
</p>
<p className='text-center text-base font-light text-[#F00]'>
รับเกียรติบัตร เนื่องจากไม่ได้เข้าร่วมงาน Onsite
</p>
</div>

{/* Footer */}
<div className='flex flex-col items-center justify-center gap-8 bg-white pb-6'>
<div>
<p className='text-center text-base font-light text-[#064E41]'>
หากมีข้อผิดพลาด สามารถกรอกข้อมูลได้ที่:
</p>
<Link href='/'>
<p className='text-center text-base font-medium text-[#064E41] underline'>
ขอรับเกียรติบัตร
</p>
</Link>
</div>
<Button className='px-10 shadow-xl' onClick={goBack}>
<p className='text-xl text-white'>กลับ</p>
</Button>
</div>
</div>
)
}

export default EvaluationFail
25 changes: 17 additions & 8 deletions src/app/(app)/evaluation/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ import {
type EvaluationForm,
EvaluationSchema,
} from '@/types/evaluation-schema'

import EvaluationFail from './fail'
import EvaluationRegister from './register'
import Success from '../../../components/register/subpages/success'

const Register: React.FC = () => {
const [step, setStep] = useState(1)
const EvaluationCheck: React.FC = () => {
const [step, setStep] = useState<number>(1)
const [foundUser, setFoundUser] = useState<boolean>(false)

const form = useForm<EvaluationForm>({
resolver: zodResolver(EvaluationSchema),
Expand All @@ -30,12 +32,19 @@ const Register: React.FC = () => {
const getPage = (): ReactNode => {
switch (step) {
case 1:
return <EvaluationForm1 form={form} setStep={setStep} />
return (
<EvaluationRegister setFoundUser={setFoundUser} setStep={setStep} />
)
case 2:
return <EvaluationForm2 form={form} setStep={setStep} />
if (foundUser) {
return <EvaluationForm1 form={form} setStep={setStep} />
}
return <EvaluationFail />
case 3:
return <EvaluationForm3 form={form} setStep={setStep} />
return <EvaluationForm2 form={form} setStep={setStep} />
case 4:
return <EvaluationForm3 form={form} setStep={setStep} />
case 5:
return <Success />
default:
return <div>404</div>
Expand All @@ -46,7 +55,7 @@ const Register: React.FC = () => {
<div>
<Toaster position='top-center' />
<Navbar />
{[1, 2, 3].includes(step) && (
{[2, 3, 4].includes(step) && (
<div className='flex flex-col items-center justify-center gap-4 bg-[#FAE9F3] py-6'>
<object
className='h-[125px] w-[125px]'
Expand All @@ -72,4 +81,4 @@ const Register: React.FC = () => {
)
}

export default Register
export default EvaluationCheck
138 changes: 138 additions & 0 deletions src/app/(app)/evaluation/register.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
'use client'

import { zodResolver } from '@hookform/resolvers/zod'
import Image from 'next/image'
import { useState } from 'react'
import { useForm } from 'react-hook-form'

import { config } from '@/app/config'
import Popup from '@/components/evaluation/popup'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { type RegisterForm, RegisterSchema } from '@/types/register'

interface EvaluationRegisterProps {
setStep: (step: number) => void
setFoundUser: (found: boolean) => void
}

const EvaluationRegister: React.FC<EvaluationRegisterProps> = ({
setStep,
setFoundUser: _setFoundUser, // marked unused
}) => {
const [showPopup, setShowPopup] = useState<boolean>(false)

const form = useForm<RegisterForm>({
resolver: zodResolver(RegisterSchema),
defaultValues: {},
})

const goBack = (): void => {
console.log('Go Back')
}

const onConfirm = (): void => {
const values = form.getValues()
console.log('Confirmed:', values)

// Implement setFoundUser later

setShowPopup(false)
setStep(2)
}

const openPopup = async (): Promise<void> => {
const requiredFields: (keyof RegisterForm)[] = ['name', 'surname']
let isAllValid = true

for (const field of requiredFields) {
const isValid = await form.trigger(field)
const input = document.querySelector(`input[name="${field}"]`)
if (isValid) {
input?.classList.remove('border-red-500')
} else {
input?.classList.add('border-red-500')
isAllValid = false
}
}

if (isAllValid) {
setShowPopup(true)
}
}

return (
<div className='flex flex-col justify-center bg-[#FAE9F3] font-mitr'>
{showPopup ? <Popup
fullName={`${form.watch('name')} ${form.watch('surname')}`}
setShowPopup={setShowPopup}
onConfirm={onConfirm}
/> : null}

{/* Logo */}
<div className='flex flex-col items-center justify-center gap-4 py-6'>
<object
className='h-[125px] w-[125px]'
data={`${config.cdnURL}/assets/register/oph-logo.svg`}
type='image/svg+xml'
>
<Image
alt='logo'
height={125}
src={`${config.cdnURL}/assets/register/oph-logo.svg`}
width={125}
/>
</object>
<div className='flex flex-col items-center text-[#064E41]'>
<div className='text-xl font-medium'>แบบประเมิน</div>
<div className='text-xl font-medium'>Chula Open House 2025</div>
</div>
</div>

{/* Entry */}
<div className='flex flex-col items-center justify-center gap-6 bg-white py-6'>
<div className='text-center text-base font-light text-[#F00]'>
<p>โปรดตรวจสอบชื่อ-นามสกุลของท่าน</p>
<p>ก่อนทำแบบประเมิน</p>
</div>

<div className='flex flex-col items-center justify-center gap-2'>
<Input
className='h-9 border-[#064E41] text-sm font-light text-[#064E41] placeholder:text-[#064E41] placeholder:opacity-50 focus-visible:ring-[#064E41]'
placeholder='Name'
{...form.register('name')}
name='name'
onInput={(e) => {
e.currentTarget.classList.remove('border-red-500')
}}
/>
<Input
className='h-9 border-[#064E41] text-sm font-light text-[#064E41] placeholder:text-[#064E41] placeholder:opacity-50 focus-visible:ring-[#064E41]'
placeholder='Surname'
{...form.register('surname')}
name='surname'
onInput={(e) => {
e.currentTarget.classList.remove('border-red-500')
}}
/>
</div>

<p className='text-center text-base font-light text-[#F00]'>
*หากยืนยันแล้วจะไม่สามารถแก้ไขได้
</p>

{/* Buttons */}
<div className='flex gap-4'>
<Button className='px-10 shadow-xl' onClick={goBack}>
<p className='text-xl text-white'>กลับ</p>
</Button>
<Button className='px-10 shadow-xl' onClick={openPopup}>
<p className='text-xl text-white'>ยืนยัน</p>
</Button>
</div>
</div>
</div>
)
}

export default EvaluationRegister
13 changes: 8 additions & 5 deletions src/app/(app)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import {
import { useAuth } from '@/hooks/use-auth'
import { getTimer } from '@/utils/timer'

import EvaluationCheck from './evaluation/page'

const Home: React.FC = () => {
const isEvaluated = true
const { isAuthenticated } = useAuth()
const isRegistered = isAuthenticated
const openRegisteredDate = new Date('2025-03-14T00:00:00').getTime()
Expand All @@ -31,14 +34,16 @@ const Home: React.FC = () => {
const interval = setInterval(() => {
setTimeLeft(getTimer())
}, 1000)

return () => clearInterval(interval)
}, [])

const actionButtonsDetail = isRegistered
? actionButtonsRegistered
: actionButtonsNotRegistered

// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (isEvaluated) return <EvaluationCheck />

return (
<div className='flex flex-col justify-center bg-[#FCF3F8]'>
<Popup />
Expand All @@ -56,11 +61,9 @@ const Home: React.FC = () => {
</p>
</Link>
</Button>
{timeLeft && timeLeft.nowDate < openRegisteredDate ? (
<p className='font-mitr text-[15px] font-normal text-[#064E41]'>
{timeLeft && timeLeft.nowDate < openRegisteredDate ? <p className='font-mitr text-[15px] font-normal text-[#064E41]'>
พร้อมลงทะเบียนวันที่ 14 มีนาคมนี้
</p>
) : null}
</p> : null}
</>
)}
<div className='grid w-full grid-cols-2 gap-2'>
Expand Down
71 changes: 71 additions & 0 deletions src/components/evaluation/popup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
'use client'

import { X } from 'lucide-react'

import {
Dialog,
DialogClose,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog'

import { Button } from '../ui/button'

interface PopupProps {
setShowPopup: (open: boolean) => void
fullName: string
onConfirm: () => void
}

const Popup: React.FC<PopupProps> = ({ setShowPopup, fullName, onConfirm }) => {
const closePopup = (): void => {
setShowPopup(false)
}

return (
<Dialog open onOpenChange={setShowPopup}>
<DialogContent className='flex w-[322px] flex-col items-center gap-6 rounded-xl border-0 bg-white font-mitr sm:max-w-md'>
{/* Header */}
<DialogHeader className='flex flex-col items-center p-0'>
<DialogClose className='absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-0'>
<X className='h-4 w-4' />
<span className='sr-only'>Close</span>
</DialogClose>
<div className='mt-4 flex flex-col items-center justify-center gap-2'>
<DialogTitle className='text-3xl font-normal text-[#f00]'>
ตรวจสอบ!!
</DialogTitle>
<p className='text-sm font-light text-[#f00]'>
ชื่อ-นามสกุลบนเกียรติบัตรของท่านคือ
</p>
</div>
</DialogHeader>

{/* Firstname - Lastname */}
<div className='h-fit w-fit rounded border border-[#064E41] px-4 py-2 text-center text-xl font-normal text-[#064E41]'>
{fullName}
</div>

<p className='text-center text-base font-light text-[#F00]'>
*หากยืนยันแล้วจะไม่สามารถแก้ไขได้
</p>

{/* Footer */}
<DialogFooter className='sm:justify-center'>
<div className='flex gap-4'>
<Button className='px-10 shadow-xl' onClick={closePopup}>
<p className='text-xl text-white'>แก้ไข</p>
</Button>
<Button className='px-10 shadow-xl' onClick={onConfirm}>
<p className='text-xl text-white'>ยืนยัน</p>
</Button>
</div>
</DialogFooter>
</DialogContent>
</Dialog>
)
}

export default Popup