<commit_before>import { Box, Separator, Serif } from "@artsy/palette"
import {
  ConfirmBidCreateBidderPositionMutation,
  ConfirmBidCreateBidderPositionMutationResponse,
} from "__generated__/ConfirmBidCreateBidderPositionMutation.graphql"
import { routes_ConfirmBidQueryResponse } from "__generated__/routes_ConfirmBidQuery.graphql"
import { BidFormFragmentContainer as BidForm } from "Apps/Auction/Components/BidForm"
import { LotInfoFragmentContainer as LotInfo } from "Apps/Auction/Components/LotInfo"
import { AppContainer } from "Apps/Components/AppContainer"
import { trackPageViewWrapper } from "Apps/Order/Utils/trackPageViewWrapper"
import { track } from "Artsy"
import * as Schema from "Artsy/Analytics/Schema"
import { FormikActions } from "formik"
import qs from "qs"
import React from "react"
import { Title } from "react-head"
import {
  commitMutation,
  createFragmentContainer,
  graphql,
  RelayProp,
} from "react-relay"
import { TrackingProp } from "react-tracking"
import { data as sd } from "sharify"
import { get } from "Utils/get"
import createLogger from "Utils/logger"

const logger = createLogger("Apps/Auction/Routes/ConfirmBid")

interface ConfirmBidProps {
  artwork: routes_ConfirmBidQueryResponse["artwork"]
  me: routes_ConfirmBidQueryResponse["me"]
  relay: RelayProp
  location: Location
  tracking: TrackingProp
}

export const ConfirmBidRoute: React.FC<ConfirmBidProps> = props => {
  const { me, artwork, tracking } = props
  const { saleArtwork } = artwork
  const { sale } = saleArtwork
  logger.log({
    me,
    sale,
    artwork,
    saleArtwork,
  })

  function createBidderPosition(maxBidAmountCents: number) {
    return new Promise(async (resolve, reject) => {
      commitMutation<ConfirmBidCreateBidderPositionMutation>(
        props.relay.environment,
        {
          onCompleted: data => {
            resolve(data)
          },
          onError: error => {
            reject(error)
          },
          mutation: graphql`
            mutation ConfirmBidCreateBidderPositionMutation(
              $input: BidderPositionInput!
            ) {
              createBidderPosition(input: $input) {
                result {
                  position {
                    id
                  }
                  status
                  message_header
                  message_description_md
                }
              }
            }
          `,
          variables: {
            input: {
              sale_id: sale.id,
              artwork_id: artwork.id,
              max_bid_amount_cents: maxBidAmountCents,
            },
          },
        }
      )
    })
  }

  function handleMutationError(
    actions: FormikActions<object>,
    error: Error,
    bidderId: string
  ) {
    logger.error(error)

    let errorMessages: string[]
    if (Array.isArray(error)) {
      errorMessages = error.map(e => e.message)
    } else if (typeof error === "string") {
      errorMessages = [error]
    } else if (error.message) {
      errorMessages = [error.message]
    }

    trackConfirmBidFailed(bidderId, errorMessages)

    actions.setSubmitting(false)
    actions.setStatus("submissionFailed")
  }

  const commonEventProperties = {
    auction_slug: sale.id,
    artwork_slug: artwork.id,
    sale_id: sale._id,
    user_id: me.id,
  }

  function trackConfirmBidFailed(bidderId: string, errors: string[]) {
    tracking.trackEvent({
      action_type: Schema.ActionType.ConfirmBidFailed,
      bidder_id: bidderId,
      error_messages: errors,
      ...commonEventProperties,
    })
  }

  function trackConfirmBidSuccess(positionId: string, bidderId: string) {
    tracking.trackEvent({
      action_type: Schema.ActionType.ConfirmBidSubmitted,
      bidder_position_id: positionId,
      bidder_id: bidderId,
      ...commonEventProperties,
    })
  }

  function handleSubmit(
    values: { selectedBid: number },
    actions: FormikActions<object>
  ) {
    const bidderId = sale.registrationStatus.id
    createBidderPosition(Number(values.selectedBid))
      .then((data: ConfirmBidCreateBidderPositionMutationResponse) => {
        if (data.createBidderPosition.result.status !== "SUCCESS") {
          trackConfirmBidFailed(bidderId, [
            "ConfirmBidCreateBidderPositionMutation failed",
          ])
        } else {
          const positionId = data.createBidderPosition.result.position.id
          trackConfirmBidSuccess(positionId, bidderId)
          window.location.assign(
            `${sd.APP_URL}/auction/${sale.id}/artwork/${artwork.id}`
          )
        }
      })
      .catch(error => {
        handleMutationError(actions, error, bidderId)
      })
      .finally(() => {
        actions.setSubmitting(false)
      })
  }

  return (
    <AppContainer>
      <Title>Auction Registration</Title>
      <Box maxWidth={550} px={[2, 0]} mx="auto" mt={[1, 0]} mb={[1, 100]}>
        <Serif size="8">Confirm your bid</Serif>
        <Separator />
        <LotInfo artwork={artwork} saleArtwork={artwork.saleArtwork} />
        <Separator />
        <BidForm
          initialSelectedBid={getInitialSelectedBid(props.location)}
          showPricingTransparency={false}
          saleArtwork={saleArtwork}
          onSubmit={handleSubmit}
        />
      </Box>
    </AppContainer>
  )
}

const getInitialSelectedBid = (location: Location): string | undefined => {
  return get(
    qs,
    querystring => querystring.parse(location.search.slice(1)).bid,
    undefined
  )
}

const TrackingWrappedConfirmBidRoute: React.FC<ConfirmBidProps> = props => {
  const Component = track({
    context_page: Schema.PageName.AuctionConfirmBidPage,
  })(ConfirmBidRoute)

  return <Component {...props} /><commit_msg>Fix title of Confirm Bid route (#2960)<commit_after>import { Box, Separator, Serif } from "@artsy/palette"
import {
  ConfirmBidCreateBidderPositionMutation,
  ConfirmBidCreateBidderPositionMutationResponse,
} from "__generated__/ConfirmBidCreateBidderPositionMutation.graphql"
import { routes_ConfirmBidQueryResponse } from "__generated__/routes_ConfirmBidQuery.graphql"
import { BidFormFragmentContainer as BidForm } from "Apps/Auction/Components/BidForm"
import { LotInfoFragmentContainer as LotInfo } from "Apps/Auction/Components/LotInfo"
import { AppContainer } from "Apps/Components/AppContainer"
import { trackPageViewWrapper } from "Apps/Order/Utils/trackPageViewWrapper"
import { track } from "Artsy"
import * as Schema from "Artsy/Analytics/Schema"
import { FormikActions } from "formik"
import qs from "qs"
import React from "react"
import { Title } from "react-head"
import {
  commitMutation,
  createFragmentContainer,
  graphql,
  RelayProp,
} from "react-relay"
import { TrackingProp } from "react-tracking"
import { data as sd } from "sharify"
import { get } from "Utils/get"
import createLogger from "Utils/logger"

const logger = createLogger("Apps/Auction/Routes/ConfirmBid")

interface ConfirmBidProps {
  artwork: routes_ConfirmBidQueryResponse["artwork"]
  me: routes_ConfirmBidQueryResponse["me"]
  relay: RelayProp
  location: Location
  tracking: TrackingProp
}

export const ConfirmBidRoute: React.FC<ConfirmBidProps> = props => {
  const { me, artwork, tracking } = props
  const { saleArtwork } = artwork
  const { sale } = saleArtwork
  logger.log({
    me,
    sale,
    artwork,
    saleArtwork,
  })

  function createBidderPosition(maxBidAmountCents: number) {
    return new Promise(async (resolve, reject) => {
      commitMutation<ConfirmBidCreateBidderPositionMutation>(
        props.relay.environment,
        {
          onCompleted: data => {
            resolve(data)
          },
          onError: error => {
            reject(error)
          },
          mutation: graphql`
            mutation ConfirmBidCreateBidderPositionMutation(
              $input: BidderPositionInput!
            ) {
              createBidderPosition(input: $input) {
                result {
                  position {
                    id
                  }
                  status
                  message_header
                  message_description_md
                }
              }
            }
          `,
          variables: {
            input: {
              sale_id: sale.id,
              artwork_id: artwork.id,
              max_bid_amount_cents: maxBidAmountCents,
            },
          },
        }
      )
    })
  }

  function handleMutationError(
    actions: FormikActions<object>,
    error: Error,
    bidderId: string
  ) {
    logger.error(error)

    let errorMessages: string[]
    if (Array.isArray(error)) {
      errorMessages = error.map(e => e.message)
    } else if (typeof error === "string") {
      errorMessages = [error]
    } else if (error.message) {
      errorMessages = [error.message]
    }

    trackConfirmBidFailed(bidderId, errorMessages)

    actions.setSubmitting(false)
    actions.setStatus("submissionFailed")
  }

  const commonEventProperties = {
    auction_slug: sale.id,
    artwork_slug: artwork.id,
    sale_id: sale._id,
    user_id: me.id,
  }

  function trackConfirmBidFailed(bidderId: string, errors: string[]) {
    tracking.trackEvent({
      action_type: Schema.ActionType.ConfirmBidFailed,
      bidder_id: bidderId,
      error_messages: errors,
      ...commonEventProperties,
    })
  }

  function trackConfirmBidSuccess(positionId: string, bidderId: string) {
    tracking.trackEvent({
      action_type: Schema.ActionType.ConfirmBidSubmitted,
      bidder_position_id: positionId,
      bidder_id: bidderId,
      ...commonEventProperties,
    })
  }

  function handleSubmit(
    values: { selectedBid: number },
    actions: FormikActions<object>
  ) {
    const bidderId = sale.registrationStatus.id
    createBidderPosition(Number(values.selectedBid))
      .then((data: ConfirmBidCreateBidderPositionMutationResponse) => {
        if (data.createBidderPosition.result.status !== "SUCCESS") {
          trackConfirmBidFailed(bidderId, [
            "ConfirmBidCreateBidderPositionMutation failed",
          ])
        } else {
          const positionId = data.createBidderPosition.result.position.id
          trackConfirmBidSuccess(positionId, bidderId)
          window.location.assign(
            `${sd.APP_URL}/auction/${sale.id}/artwork/${artwork.id}`
          )
        }
      })
      .catch(error => {
        handleMutationError(actions, error, bidderId)
      })
      .finally(() => {
        actions.setSubmitting(false)
      })
  }

  return (
    <AppContainer>
      <Title>Confirm Bid | Artsy</Title>
      <Box maxWidth={550} px={[2, 0]} mx="auto" mt={[1, 0]} mb={[1, 100]}>
        <Serif size="8">Confirm your bid</Serif>
        <Separator />
        <LotInfo artwork={artwork} saleArtwork={artwork.saleArtwork} />
        <Separator />
        <BidForm
          initialSelectedBid={getInitialSelectedBid(props.location)}
          showPricingTransparency={false}
          saleArtwork={saleArtwork}
          onSubmit={handleSubmit}
        />
      </Box>
    </AppContainer>
  )
}

const getInitialSelectedBid = (location: Location): string | undefined => {
  return get(
    qs,
    querystring => querystring.parse(location.search.slice(1)).bid,
    undefined
  )
}

const TrackingWrappedConfirmBidRoute: React.FC<ConfirmBidProps> = props => {
  const Component = track({
    context_page: Schema.PageName.AuctionConfirmBidPage,
  })(ConfirmBidRoute)

  return <Component {...props} />
{'fraction_non_alphanumeric': 0.10422486033519553, 'fraction_numerical': 0.0026187150837988825, 'mean_word_length': 2.696999031945789, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1440', 'n_tokens_mistral': 3477, 'n_tokens_neox': 3424, 'n_words': 637}