Untitled
unknown
javascript
4 years ago
22 kB
5
Indexable
import { useState, useEffect } from 'react'
import { Formik, Form, Field, ErrorMessage } from 'formik'
import { SaveIcon } from '@heroicons/react/solid'
import Link from 'next/link'
import Image from 'next/image'
import { useRouter } from 'next/router'
import * as Yup from 'yup'
import LayoutGrid from '../../../components/admin/layout-grid'
import ListBox from '../../../components/ui/listbox'
import { position, role, branch } from '../../../data/personnel'
import DatePickerField from '../../../components/ui/datepicker'
// form validations
const schema = Yup.object().shape({
employee: Yup.boolean().required(),
username: Yup.string().required('Username is required'),
password: Yup.string()
.required('Passcode is required')
.min(6, 'Passcode must be at least 6 digits')
.max(32, 'Passcode is too long'),
startDate: Yup.date().required('Start Date is required'),
firstName: Yup.string().required('First name is required'),
lastName: Yup.string().required('Last name is required'),
birthday: Yup.date().required('Birthay is required'),
address: Yup.string().required('Street Address is required'),
city: Yup.string().required('City is required'),
state: Yup.string().required('State/Province required'),
zip: Yup.string()
.required('ZIP / Postal is required')
.matches(/^[0-9]+$/, 'ZIP must be only digits')
.min(4, 'ZIP must be 4 digits')
.max(10, 'ZIP is too long'),
notes: Yup.string().required('Notes is required'),
})
export default function AddNewPage({ tokens }) {
const [isRole, setIsRole] = useState(role[0])
const [isBranch, setIsBranch] = useState(branch[0])
const [isPosition, setIsPosition] = useState(position[0])
const [image, setImage] = useState()
const [preview, setPreview] = useState()
const selectedImg = (e) => {
const file = e.target.files[0]
if (file) {
setImage(file)
} else {
setImage(null)
}
}
const [user, setUser] = useState({})
const router = useRouter()
const { accessToken, refreshTokenID } = JSON.parse(tokens)
useEffect(() => authorizationCallback(), [])
const authorizationCallback = async () => {
try {
if (accessToken && refreshTokenID) {
const authorizationResponse = await fetch(
`/api/tokenHandler?refreshTokenID=${refreshTokenID}`,
{
method: 'GET',
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
)
const authorizationStatus = authorizationResponse.status
if (authorizationStatus === 401 || authorizationStatus === 403) {
return router.push('/sign-in')
}
const { data } = await authorizationResponse.json()
setUser(data)
} else {
return router.push('/sign-in')
}
} catch (error) {
console.error(error)
}
}
const logoutCallback = async () => {
try {
await fetch('/api/logout', {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
refreshTokenID,
}),
})
} catch (error) {
console.error(error)
}
}
// create a preview as a side effect, whenever selected file is changed
useEffect(() => {
if (image) {
const reader = new FileReader()
reader.onloadend = () => {
setPreview(reader.result)
}
reader.readAsDataURL(image)
} else {
setPreview(null)
}
}, [image])
return (
<LayoutGrid logout={logoutCallback} user={user}>
<header className="flex items-center justify-between mb-12">
<h1 className="text-3xl font-bold text-gray-900">Personnel</h1>
<Link href="/admin/personnel/">
<a className="text-sm font-medium text-indigo-600">Cancel</a>
</Link>
</header>
{/* content */}
<Formik
initialValues={{
employed: true,
image: '',
username: '',
password: '',
startDate: new Date(),
firstName: '',
middle_name: '',
lastName: '',
birthday: new Date(),
address: '',
city: '',
state: '',
zip: '',
role: isRole,
branch: isBranch,
position: isPosition,
notes: '',
}}
validationSchema={schema}
onSubmit={(values) => {
console.log(1)
alert(1)
// try{
// const response = await fetch();
// }catch(error){
// console.error(error.message)
// }
}}
>
{(formik) => (
<Form>
<div className="flex items-center justify-between text-sm font-bold">
<h3>New Personal</h3>
<button
// disabled={formik.isSubmitting}
type="submit"
className="flex items-center justify-center w-24 space-x-2 text-sm btn btn-primary"
>
<SaveIcon className="h-5" />
<span>Save</span>
</button>
</div>
{/* change photo */}
<div className="flex items-end justify-between mt-11">
<div className="space-y-2">
<h4 className="label">Photo</h4>
<div className="flex items-center space-x-5">
<div className="relative h-11 w-11">
<Image
src={preview ? preview : '/images/user-photo.svg'}
alt="Upload an image"
layout="fill"
objectFit="cover"
className="rounded-full"
/>
</div>
<button
type="button"
className="text-sm font-medium text-gray-800 transition duration-200 ease-in-out bg-white rounded-md focus:outline-none ring-2 ring-gray-200 focus:ring-indigo-600 focus:ring-offset-2 focus:ring-opacity-75 focus:bg-indigo-600 focus:text-white hover:bg-indigo-600 hover:text-white hover:ring-indigo-600"
>
<label
htmlFor="myImage"
className="block cursor-pointer px-3 py-1.5"
>
<Field
type="file"
name="image"
id="myImage"
accept="image/*"
className="hidden"
value={undefined}
onChange={(e) => {
formik.setFieldValue('img', e.currentTarget.files[0])
selectedImg(e)
}}
/>
Change
</label>
</button>
</div>
</div>
<div>
<label className="inline-flex items-center space-x-3 label">
<Field
type="checkbox"
name="employed"
className="text-indigo-600 rounded focus:ring focus:ring-indigo-300 focus:ring-offset-0 focus:ring-opacity-50"
/>
<span className="select-none">Employed</span>
</label>
</div>
</div>
{/* inputs */}
<div className="pb-7 mt-7">
{/* 1st row */}
<div className="grid items-center justify-between grid-cols-1 md:grid-cols-3 gap-x-7">
<div className="relative flex flex-col space-y-1 pb-7">
{formik.errors.username && formik.touched.username ? (
<ErrorMessage
name="username"
className="text-sm text-red-500 label "
component="label"
htmlFor="username"
/>
) : (
<label className="label" htmlFor="username">
Username
</label>
)}
<Field
name="username"
id="username"
type="text"
id="username"
className={` form-control ${
formik.errors.username && formik.touched.username
? 'error '
: 'form-control '
}`}
/>
</div>
<div className="relative flex flex-col space-y-1 pb-7">
{formik.errors.password && formik.touched.password ? (
<ErrorMessage
name="password"
className="text-sm text-red-500 label "
component="label"
htmlFor="password"
/>
) : (
<label className="label" htmlFor="password">
Passcode (6-digits)
</label>
)}
<Field
name="password"
id="password"
type="password"
placeholder="••••••"
className={` form-control ${
formik.errors.password && formik.touched.password
? 'error '
: 'form-control '
}`}
/>
</div>
<div className="relative flex flex-col space-y-1 pb-7">
{formik.errors.startDate && formik.touched.startDate ? (
<ErrorMessage
name="startDate"
className="text-sm text-red-500 label "
component="label"
htmlFor="startDate"
/>
) : (
<label className="label" htmlFor="startDate">
Start Date
</label>
)}
<div className="relative -mt-1">
<DatePickerField
name="startDate"
aria="start date"
id="startDate"
/>
</div>
</div>
</div>
{/* 2nd row */}
<div className="grid items-center justify-between grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-7">
<div className="relative flex flex-col space-y-1 pb-7">
{formik.errors.firstName && formik.touched.firstName ? (
<ErrorMessage
name="firstName"
className="text-sm text-red-500 label "
component="label"
htmlFor="firstName"
/>
) : (
<label className="label" htmlFor="firstName">
First name
</label>
)}
<Field
name="firstName"
id="firstName"
type="text"
className={` form-control ${
formik.errors.firstName && formik.touched.firstName
? 'error '
: 'form-control '
}`}
/>
</div>
<div className="grid grid-cols-1 md:row-[2/3] lg:row-auto lg:grid-cols-2 gap-x-7">
<div className="relative flex flex-col space-y-1 pb-7 md:hidden lg:flex">
<label className="label" htmlFor="middle_name">
Middle name
</label>
<Field
name="middle_name"
id="middle_name"
type="text"
className={` form-control ${
formik.errors.middle_name && formik.touched.middle_name
? 'error '
: 'form-control '
}`}
/>
</div>
<div className="relative flex flex-col space-y-1 pb-7 ">
{formik.errors.lastName && formik.touched.lastName ? (
<ErrorMessage
name="lastName"
className="text-sm text-red-500 label "
component="label"
htmlFor="lastName"
/>
) : (
<label className="label" htmlFor="lastName">
Last name
</label>
)}
<Field
name="lastName"
id="lastName"
type="text"
className={` form-control ${
formik.errors.lastName && formik.touched.lastName
? 'error '
: 'form-control '
}`}
/>
</div>
</div>
<div className="relative flex-col hidden space-y-1 pb-7 md:flex lg:hidden">
<label className="label" htmlFor="middle_name_2">
Middle name
</label>
<Field
name="middle_name"
id="middle_name_2"
type="text"
className={` form-control ${
formik.errors.middle_name && formik.touched.middle_name
? 'error '
: 'form-control '
}`}
/>
</div>
<div className="relative flex flex-col space-y-1 pb-7">
{formik.errors.birthday && formik.touched.birthday ? (
<ErrorMessage
name="birthday"
className="text-sm text-red-500 label "
component="label"
htmlFor="birthday"
/>
) : (
<label className="label" htmlFor="birthday">
Birthday
</label>
)}
<div className="relative -mt-1">
<DatePickerField
name="birthday"
aria="birthday"
id="birthday"
/>
</div>
</div>
</div>
{/* 3rd row */}
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-x-7 xl:grid-cols-input-grid">
<div className="relative flex flex-col space-y-1 pb-7">
{formik.errors.address && formik.touched.address ? (
<ErrorMessage
name="address"
className="text-sm text-red-500 label "
component="label"
htmlFor="address"
/>
) : (
<label className="label" htmlFor="address">
Street Address
</label>
)}
<Field
name="address"
id="address"
type="text"
className={` form-control ${
formik.errors.address && formik.touched.address
? 'error '
: 'form-control '
}`}
/>
</div>
<div className="relative flex flex-col space-y-1 pb-7">
{formik.errors.city && formik.touched.city ? (
<ErrorMessage
name="city"
className="text-sm text-red-500 label "
component="label"
htmlFor="city"
/>
) : (
<label className="label" htmlFor="city">
City
</label>
)}
<Field
name="city"
id="city"
type="text"
className={` form-control ${
formik.errors.city && formik.touched.city
? 'error '
: 'form-control '
}`}
/>
</div>
<div className="relative flex flex-col space-y-1 pb-7">
{formik.errors.state && formik.touched.state ? (
<ErrorMessage
name="state"
className="text-sm text-red-500 label "
component="label"
htmlFor="state"
/>
) : (
<label className="label" htmlFor="state">
State / Province
</label>
)}
<Field
name="state"
id="state"
type="text"
className={` form-control ${
formik.errors.state && formik.touched.state
? 'error '
: 'form-control '
}`}
/>
</div>
<div className="relative flex flex-col space-y-1 pb-7">
{formik.errors.zip && formik.touched.zip ? (
<ErrorMessage
name="zip"
className="text-sm text-red-500 label "
component="label"
htmlFor="zip"
/>
) : (
<label className="label" htmlFor="zip">
ZIP / Postal
</label>
)}
<Field
name="zip"
id="zip"
type="text"
className={` form-control ${
formik.errors.zip && formik.touched.zip
? 'error '
: 'form-control '
}`}
/>
</div>
</div>
{/* 4th row */}
<div className="grid grid-cols-1 gap-y-6 md:gap-y-0 md:grid-cols-3 gap-x-7 xl:grid-cols-input-grid-2 pb-7">
<div className="flex flex-col space-y-1 ">
<ListBox
label="Role"
options={role}
name="role"
id="role_type"
/>
</div>
<div className="flex flex-col space-y-1 ">
<ListBox
label="Branch"
options={branch}
name="branch"
id="branch_type"
/>
</div>
<div className="flex flex-col space-y-1 ">
<ListBox
label="Full-time/Part-time"
options={position}
name="position"
id="position_type"
/>
</div>
</div>
{/* 5th row - TEXTAREA */}
<div className="relative flex flex-col space-y-1 pb-7 ">
{formik.errors.notes && formik.touched.notes ? (
<ErrorMessage
name="notes"
className="text-sm text-red-500 label "
component="label"
htmlFor="notes"
/>
) : (
<label className="label" htmlFor="notes">
Notes
</label>
)}
<Field
name="notes"
id="notes"
as="textarea"
rows="5"
className={` form-control ${
formik.errors.notes && formik.touched.notes
? 'error '
: 'form-control '
}`}
/>
</div>
{/* BUTTON */}
<div className="flex items-center justify-end">
<button
// disabled={formik.isSubmitting}
type="submit"
className="flex items-center justify-center w-24 space-x-2 btn btn-primary"
>
<SaveIcon className="h-5" />
<span>Save</span>
</button>
</div>
</div>
</Form>
)}
</Formik>
</LayoutGrid>
)
}
export async function getServerSideProps({ req, res }) {
return {
props: {
tokens: req.cookies.tokens || '{}',
},
}
}
Editor is loading...