Untitled
unknown
javascript
3 years ago
22 kB
4
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...