import React , { useState , useCallback } from "react" ; import styled from "styled-components" ; import media from "src/utils/media" ; import copy from "src/copy" ; import { Button } from "@hackthenorth/north" ; import Body from "src/components/Body" ; import TextInput from "src/components/TextInput" ; declare global { interface Window { HackerAPI : any ; } } interface FormProps { width : string ; } interface MailingListProps { isFooter ? : boolean ; } const REVERT_STATE_TIME = 2500 ; const validateEmailAddress = ( email ) => { const emailPrefix = "[A-Z0-9a-z]([A-Z0-9a-z._%+-]{0,30}[A-Z0-9a-z])?" ; const emailServer = "([A-Z0-9a-z]([A-Z0-9a-z-]{0,30}[A-Z0-9a-z])?\\.){1,5}" ; const emailRegEx = `${ emailPrefix }@${ emailServer }[A-Za-z]{2,6}` ; if ( email . match ( emailRegEx ) ) { return true ; } return false ; } ; const Container = styled . form < FormProps > `
  position: relative;
  width: ${ props => props . width };
  height: 50px;
  margin: 0 auto;
  position: relative;

  font-family: Raleway;
  line-height: 100%;

  ${ media . phone `
    width: 85vw;
    height: 40px;
    font-size: 14px;
  ` }
` ; const SubText = styled ( Body ) `
  margin-top: 10px;
  text-align: center;
  z-index: 1;
  color: ${ props => props . color };

  ${ media . phone `
    width: 75vw;
    margin: 10px auto;
    font-size: 12px;
  ` }
` ; const AnimSpan = styled . span `
  @keyframes shake {
    0% {
      transform: translate(4px, 0);
    }
    50% {
      transform: translate(-4px, 0);
    }
    100% {
      transform: translate(0, 0);
    }
  }

  position: absolute;
  right: 0;
  width: 170px;
  height: 100%;

  &.shake {
    animation: shake 200ms 2 linear;
  }
` ; const MailingListSignup = ( { isFooter } ) => { const [ signupState , updateSignupState ] = useState ( "ready" ) ; const [ canSubmit , updateCanSubmit ] = useState ( true ) ; const [ email , updateEmail ] = useState ( "" ) ; const [ shouldShake , toggleShake ] = useState ( false ) ; const { HackerAPI } = window ; const triggerError = ( newState ) => { updateSignupState ( newState ) ; updateCanSubmit ( true ) ; toggleShake ( true ) ; setTimeout ( ( ) => { updateSignupState ( "ready" ) ; } , REVERT_STATE_TIME ) ; } ; const signupForMailingList = useCallback ( e => { e . preventDefault ( ) ; if ( ! canSubmit ) return ; updateCanSubmit ( false ) ; if ( validateEmailAddress ( email ) ) { HackerAPI . Event . MailingListSignup . create ( new HackerAPI . Event ( { slug : "hackioca" } ) , new HackerAPI . Event . MailingListSignup ( { email } ) ) . then ( ( data ) => { if ( data && "email" in data ) { if ( data . alreadySignedUp ) { updateSignupState ( "dupe" ) ; toggleShake ( true ) ; } else { updateSignupState ( "success" ) ; updateEmail ( "" ) ; } } else { triggerError ( "error" ) ; } } ) . catch ( ( ) => { triggerError ( "error" ) ; } ) ; } else { triggerError ( "invalid" ) ; } setTimeout ( ( ) => { updateCanSubmit ( true ) ; } , REVERT_STATE_TIME ) ; } , [ email , canSubmit ] ) ; let buttonVariant ; switch ( signupState ) { case "ready" : break ; case "success" : buttonVariant = "success" ; break ; default : buttonVariant = "error" ; } return ( < > < Container width = { isFooter ? "100%" : "550px" } onSubmit = { e => signupForMailingList ( e ) } > < TextInput placeholder = { copy . hero . signupPlaceholder [ signupState ] } type = "email" value = { email } onChange = { ( newEmail ) => updateEmail ( newEmail ) } /> < AnimSpan className = { shouldShake ? "shake" : "" } onAnimationEnd = { ( ) => toggleShake ( false ) } > < Button variant = { buttonVariant } onClick = { signupForMailingList } > { copy . hero . button [ signupState ] } < /Button> < /AnimSpan> < /Container> < SubText color = { isFooter ? "#fff" : "" } > { copy . hero . signup [ signupState ] } < /SubText> < />); } ; export default MailingListSignup ;