import { Checkbox, Form, Input, MarkdownInput } from './form' import Row from 'react-bootstrap/Row' import Col from 'react-bootstrap/Col' import InputGroup from 'react-bootstrap/InputGroup' import Image from 'react-bootstrap/Image' import BootstrapForm from 'react-bootstrap/Form' import Alert from 'react-bootstrap/Alert' import { useEffect, useState } from 'react' import Info from './info' import AccordianItem from './accordian-item' import styles from '@/styles/post.module.css' import { useLazyQuery, gql } from '@apollo/client' import Link from 'next/link' import { usePrice } from './price' import Avatar from './avatar' import { jobSchema } from '@/lib/validate' import { MAX_TITLE_LENGTH, MEDIA_URL } from '@/lib/constants' import { ItemButtonBar } from './post' import { useFormikContext } from 'formik' import { UPSERT_JOB } from '@/fragments/paidAction' import useItemSubmit from './use-item-submit' function satsMin2Mo (minute) { return minute * 30 * 24 * 60 } function PriceHint ({ monthly }) { const { price, fiatSymbol } = usePrice() if (!price || !monthly) { return null } const fixed = (n, f) => Number.parseFloat(n).toFixed(f) const fiat = fixed((price / 100000000) * monthly, 0) return {monthly} sats/mo which is {fiatSymbol}{fiat}/mo } // need to recent list items export default function JobForm ({ item, sub }) { const storageKeyPrefix = item ? undefined : `${sub.name}-job` const [logoId, setLogoId] = useState(item?.uploadId) const extraValues = logoId ? { logo: Number(logoId) } : {} const onSubmit = useItemSubmit(UPSERT_JOB, { item, sub, extraValues }) return ( <>
remote} name='remote' hiddenLabel groupClassName={styles.inlineCheckGroup} /> how to apply url or email address} name='url' required clear /> {item && } ) } const FormStatus = { DIRTY: 'dirty', ERROR: 'error' } function PromoteJob ({ item, sub }) { const formik = useFormikContext() const [show, setShow] = useState(false) const [monthly, setMonthly] = useState(satsMin2Mo(item?.maxBid || 0)) const [getAuctionPosition, { data }] = useLazyQuery(gql` query AuctionPosition($id: ID, $bid: Int!) { auctionPosition(sub: "${item?.subName || sub?.name}", id: $id, bid: $bid) }`, { fetchPolicy: 'cache-and-network' }) const position = data?.auctionPosition useEffect(() => { const initialMaxBid = Number(item?.maxBid) || 0 getAuctionPosition({ variables: { id: item?.id, bid: initialMaxBid } }) setMonthly(satsMin2Mo(initialMaxBid)) }, []) useEffect(() => { if (formik?.values?.maxBid !== 0) { setShow(FormStatus.DIRTY) } }, [formik?.values]) useEffect(() => { const hasMaxBidError = !!formik?.errors?.maxBid // if it's open we don't want to collapse on submit setShow(show => show || (hasMaxBidError && formik?.isSubmitting && FormStatus.ERROR)) }, [formik?.isSubmitting]) return ( promote} body={ <> bid
  1. The higher your bid the higher your job will rank
  2. You can increase, decrease, or remove your bid at anytime
  3. You can edit or stop your job at anytime
  4. If you run out of sats, your job will stop being promoted until you fill your wallet again
optional } name='maxBid' onChange={async (formik, e) => { if (e.target.value >= 0 && e.target.value <= 100000000) { setMonthly(satsMin2Mo(e.target.value)) getAuctionPosition({ variables: { id: item?.id, bid: Number(e.target.value) } }) } else { setMonthly(satsMin2Mo(0)) } }} append={sats/min} hint={} /> <>
This bid puts your job in position: {position}
} /> ) } function StatusControl ({ item }) { let StatusComp if (item.status !== 'STOPPED') { StatusComp = () => { return ( <> I want to stop my job} headerColor='var(--bs-danger)' body={ stop my job} name='stop' inline /> } /> ) } } else if (item.status === 'STOPPED') { StatusComp = () => { return ( I want to resume my job} headerColor='var(--bs-success)' body={ resume my job} name='start' inline /> } /> ) } } return (
job control {item.status === 'NOSATS' && your promotion ran out of sats. fund your wallet or reduce bid to continue promoting your job}
) }