Untitled

mail@pastecode.io avatar
unknown
javascript
2 years ago
22 kB
2
Indexable
Never
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 || '{}',
    },
  }
}