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 { useCallback, useEffect, useState } from 'react' import Info from './info' import AccordianItem from './accordian-item' import styles from '../styles/post.module.css' import { useLazyQuery, gql, useMutation } from '@apollo/client' import { useRouter } from 'next/router' import Link from 'next/link' import { usePrice } from './price' import Avatar from './avatar' import { jobSchema } from '../lib/validate' import { MAX_TITLE_LENGTH } from '../lib/constants' import { useToast } from './toast' import { toastDeleteScheduled } from '../lib/form' import { ItemButtonBar } from './post' 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 router = useRouter() const toaster = useToast() const [logoId, setLogoId] = useState(item?.uploadId) const [upsertJob] = useMutation(gql` mutation upsertJob($sub: String!, $id: ID, $title: String!, $company: String!, $location: String, $remote: Boolean, $text: String!, $url: String!, $maxBid: Int!, $status: String, $logo: Int, $hash: String, $hmac: String) { upsertJob(sub: $sub, id: $id, title: $title, company: $company, location: $location, remote: $remote, text: $text, url: $url, maxBid: $maxBid, status: $status, logo: $logo, hash: $hash, hmac: $hmac) { id deleteScheduledAt } }` ) const onSubmit = useCallback( async ({ maxBid, start, stop, ...values }) => { let status if (start) { status = 'ACTIVE' } else if (stop) { status = 'STOPPED' } const { data, error } = await upsertJob({ variables: { id: item?.id, sub: item?.subName || sub?.name, maxBid: Number(maxBid), status, logo: Number(logoId), ...values } }) if (error) { throw new Error({ message: error.toString() }) } if (item) { await router.push(`/items/${item.id}`) } else { await router.push(`/~${sub.name}/recent`) } toastDeleteScheduled(toaster, data, !!item, values.text) }, [upsertJob, router, logoId] ) return ( <>
remote} name='remote' hiddenLabel groupClassName={styles.inlineCheckGroup} /> how to apply url or email address} name='url' required clear /> {item && } ) } function PromoteJob ({ item, sub }) { 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)) }, []) return ( 0} header={
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}
) }