import { Checkbox, Form, Input, MarkdownInput, SubmitButton } 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 ActionTooltip from './action-tooltip' import { jobSchema } from '../lib/validate' import CancelButton from './cancel-button' import { useInvoiceable } from './invoice' 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 [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) { upsertJob(sub: $sub, id: $id, title: $title, company: $company, location: $location, remote: $remote, text: $text, url: $url, maxBid: $maxBid, status: $status, logo: $logo) { id } }` ) const submitUpsertJob = useCallback( // we ignore the invoice since only stackers can post jobs async (_, maxBid, stop, start, values, ...__) => { let status if (start) { status = 'ACTIVE' } else if (stop) { status = 'STOPPED' } const { 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`) } }, [upsertJob, router]) const invoiceableUpsertJob = useInvoiceable(submitUpsertJob, { requireSession: true }) return ( <>
{ await invoiceableUpsertJob(1000, maxBid, stop, start, values) })} >
remote} name='remote' hiddenLabel groupClassName={styles.inlineCheckGroup} /> how to apply url or email address} name='url' required clear /> {item && }
{item ? (
save
) : ( post 1000 sats )}
) } 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}
) }