next-seo#BreadcrumbJsonLd JavaScript Examples

The following examples show how to use next-seo#BreadcrumbJsonLd. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 6 votes vote down vote up
ForumCategoryIndexPage = () => {
  return (
    <>
      <NextSeo
        title={`Remotebond Forum a hub for everything related to remote work`}
        description="The Remotebond Forum is a how-to content hub for all things remote work."
        canonical={`https://remotebond.com/forum`}
        openGraph={{
          url: `https://remotebond.com/forum`,
          title: `Remotebond Forum a hub for everything related to remote work`,
          description: `The Remotebond Forum is a how-to content hub for all things remote work.`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: "Forum",
          },
        ]}
      />
      <PageHeader
        title={`Remotebond Forum`}
        subtitle={`The Remotebond Forum is a how-to content hub for all things remote work. From best practices for job seekers, tools, resources and news to hiring tips and processes, the Remotebond forum is meant to be community-driven documentation on how to get remote work right.`}
      />
    </>
  )
}
Example #2
Source File: hire-remotely.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 5 votes vote down vote up
NewJobPage = ({ paymentIntent }) => {
  return (
    <Elements stripe={stripePromise}>
      <>
        <NextSeo
          title={`Create a new remote job post`}
          description="Start hiring remotely, post a new remote job and find the most qualified people for your next remote position."
          canonical={`https://remotebond.com/hire-remotely`}
          openGraph={{
            url: `https://remotebond.com/hire-remotely`,
            title: `Create a new remote job post`,
            description: `Start hiring remotely, post a new remote job and find the most qualified people for your next remote position.`,
          }}
        />
        <BreadcrumbJsonLd
          itemListElements={[
            {
              position: 1,
              name: "remotebond.com",
              item: "https://remotebond.com",
            },
            {
              position: 2,
              name: "Hire Remotely",
            },
          ]}
        />
        <Banner message={`Launch deal! Base job ad is now priced at $25`} />
        <div className="relative overflow-hidden bg-black">
          <div className="max-w-screen-xl mx-auto py-16 px-4 sm:px-6 lg:py-12 lg:px-8">
            <div>
              <h1 className="text-center text-3xl leading-9 font-extrabold text-white">
                Hire remotely
              </h1>
              <h2 className="text-rb-gray-4 text-center w-full">
                Create your remote job post and reach remote workers all around
                the world.
              </h2>
            </div>
          </div>
        </div>
        <JobPostForm paymentIntentSSR={paymentIntent} />
      </>
    </Elements>
  )
}
Example #3
Source File: index.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
RemoteCompaniesIndexPage = (props) => {
  const router = useRouter()
  const { companies } = props
  let date = new Date()
  let dateOptions = {
    year: "numeric",
    month: "long",
  }

  if (router.isFallback) {
    return (
      <div className="max-w-screen-xl mx-auto py-10 px-4 sm:px-6">
        <h1>Loading...</h1>
      </div>
    )
  }

  if (!companies?.length) {
    return (
      <>
        <Head>
          <meta name="robots" content="noindex" />
        </Head>
        <DefaultErrorPage statusCode={404} />
      </>
    )
  } else {
    return (
      <>
        <NextSeo
          title={`Remote Companies Hiring`}
          description={`Remote companies hiring in ${date.toLocaleDateString(
            "en-EN",
            dateOptions
          )} allowing employees to work remotely`}
          canonical={`https://remotebond.com/remote-companies`}
          openGraph={{
            url: `https://remotebond.com/remote-companies`,
            title: `Remote Companies Hiring`,
            description: `Remote companies hiring in ${date.toLocaleDateString(
              "en-EN",
              dateOptions
            )} allowing employees to work remotely`,
          }}
        />
        <BreadcrumbJsonLd
          itemListElements={[
            {
              position: 1,
              name: "remotebond.com",
              item: "https://remotebond.com",
            },
            {
              position: 2,
              name: "Remote Companies",
            },
          ]}
        />
        <div className="relative overflow-hidden bg-black">
          <div className="max-w-screen-xl mx-auto text-center py-6 md:py-12 px-4 sm:px-6">
            <h1 className="text-white font-black text-2xl md:text-4xl my-4">
              Remote Companies
            </h1>
            <h2 className="text-base md:text-xl text-rb-gray-4 w-3/4 mx-auto">
              Browse {`${companies.length}`} Remote Companies in{" "}
              {date.toLocaleDateString("en-EN", dateOptions)} who allow their
              employees to work remotely.
            </h2>
          </div>
        </div>

        <div className="w-full max-w-screen-xl mx-auto py-10 px-4 sm:px-6">
          <ul className="mt-3 grid grid-cols-1 gap-5 sm:gap-6 sm:grid-cols-2 lg:grid-cols-4">
            {companies.map((company, cidx) => {
              return (
                <li key={cidx}>
                  <Link href={`/remote-companies/${company.slug}`}>
                    <a
                      title={`View remote company profile of ${company.name}`}
                      className="col-span-1 flex shadow-sm rounded-md group hover:cursor-pointer"
                    >
                      <div className="flex-shrink-0 flex items-center justify-center w-16 bg-rb-gray-5 text-white text-sm leading-5 font-medium rounded-l-md group-hover:bg-blue-600">
                        {company.name.substring(0, 2)}
                      </div>
                      <div className="flex-1 flex items-center justify-between border-t border-r border-b border-gray-200 bg-white rounded-r-md truncate">
                        <div className="flex-1 px-4 py-2 text-sm leading-5 truncate">
                          <span className="text-gray-900 font-medium hover:text-gray-600 transition ease-in-out duration-150">
                            {company.name}
                          </span>
                          <p className="text-gray-500">
                            {company.jobsCount} Open{" "}
                            {company.jobsCount === 1 ? "position" : "positions"}
                          </p>
                        </div>
                      </div>
                    </a>
                  </Link>
                </li>
              )
            })}
          </ul>
        </div>
      </>
    )
  }
}
Example #4
Source File: [query].js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
SearchJobPage = ({ result, q }) => {
  const {
    data: { data },
  } = result

  return (
    <>
      <NextSeo
        title={`Remote ${q} jobs`}
        description={`The latest and most popular remote ${q} jobs around the web. Jobs included from top remote companies. Find your new ${q} career on Remotebond.`}
        canonical={`https://remotebond.com/search/${q}`}
        openGraph={{
          url: `https://remotebond.com/search/${q}`,
          title: `Remote ${q} jobs`,
          description: `The latest and most popular remote ${q} jobs around the web. Jobs included from top remote companies. Find your new ${q} career on Remotebond.`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: `Remote ${q} jobs`,
          },
        ]}
      />
      <div
        className={`relative overflow-hidden bg-black ${
          !data.length > 0
            ? "flex-1 items-center justify-center flex flex-row"
            : "mb-12"
        }`}
      >
        <div className="max-w-screen-xl mx-auto text-center py-6 md:py-12 px-4 sm:px-6">
          {!data.length && (
            <div className="w-full max-w-screen-xl mx-auto flex justify-center flex-col">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
                className="w-24 h-24 md:w-48 md:h-48 mb-4 text-blue-500 mx-auto"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
                />
              </svg>
              <h3 className="text-white text-xl font-bold md:text-3xl">
                Your search resulted in no results
              </h3>
              <p className="text-white text-sm md:text-base">
                Try searching with a different search query.
              </p>
            </div>
          )}
          {data?.length > 0 && (
            <>
              <div className="flex items-center justify-center">
                <h1 className="text-white font-black text-2xl md:text-4xl my-4">
                  Remote {q} Jobs
                </h1>
              </div>
              <h2 className="text-base md:text-xl text-rb-gray-4 w-3/4 mx-auto">
                Your query "{q}" resulted in {data.length} results
              </h2>
              <span className="inline-flex rounded-md shadow-sm mt-8">
                <Link href={`/hire-remotely`} as={`/hire-remotely`}>
                  <a
                    title="Post a remote job and hire remotely"
                    className="inline-flex items-center px-6 py-3 border border-transparent text-base leading-6 font-bold rounded-md text-white bg-rb-green-6 hover:bg-rb-green-5 hover:text-white focus:outline-none focus:border-rb-green-7 focus:shadow-outline-blue active:bg-rb-green-7 transition ease-in-out duration-150"
                  >
                    Post a job for $25
                  </a>
                </Link>
              </span>
            </>
          )}
        </div>
      </div>
      {data?.length > 0 && <JobsList title={q} jobs={data} />}
    </>
  )
}
Example #5
Source File: remote-sales-marketing-jobs.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
RemoteSalesMarketingPage = ({
  jobsCount,
  initialData,
  initialAfter,
  firstPubDate,
  categories,
  initialPubDate,
}) => {
  const [cursor, setCursor] = useState({
    key: initialAfter,
    date: firstPubDate,
    page: 0,
    before: null,
    isPrevClicked: false,
    isNextClicked: false,
  })
  const [isLoading, setIsLoading] = useState(false)
  const [firstRender, setFirstRender] = useState(true)

  const newJobs = () => {
    if (cursor.isPrevClicked) {
      return `/api/jobs/prev?key=${cursor.before}&d=${cursor.prevDate}`
    }

    if (!cursor.date && !cursor.isPrevClicked) {
      return `/api/jobs/next`
    } else {
      return `/api/jobs/next?key=${cursor.key}&d=${cursor.date}`
    }
  }

  const { data, mutate } = useSWR(!isLoading ? newJobs : null, fetcher)

  let date = new Date()
  let dateOptions = {
    year: "numeric",
    month: "long",
  }

  const loadMoreJobs = () => {
    setCursor({
      key: data.after[2]
        ? data.after[2]["@ref"].id
        : data.after[1]
        ? data.after[1]["@ref"].id
        : null,
      prevDate: data.before[0], //data.data[0].data.pub_date,
      date: data.after[0], //data.data.slice(-1)[0].data.pub_date,
      page: cursor.page + 1,
      before:
        data && data.before && data.before[2]
          ? data.before[2]["@ref"].id
          : data.before[1]
          ? data.before[1]["@ref"].id
          : null,
      isPrevClicked: false,
      isNextClicked: true,
    })
    setIsLoading(true)
  }

  const loadPrevPage = () => {
    setCursor({
      key:
        data.after && data.after[2]
          ? data.after[2]["@ref"].id
          : data.after && data.after[1]
          ? data.after[1]["@ref"].id
          : null,
      prevDate: data.before[0], //data.data[0].data.pub_date,
      date: data.after ? data.after[0] : null, //data.data.slice(-1)[0].data.pub_date,
      page: cursor.page - 1,
      before:
        data.before && data.before[2]
          ? data.before[2]["@ref"].id
          : data.before[1]
          ? data.before[1]["@ref"].id
          : null,
      isPrevClicked: true,
      isNextClicked: false,
    })
  }

  // Fetch new jobs on state change
  useEffect(() => {
    if (firstRender) {
      setFirstRender(false)
    } else {
      mutate()
      setIsLoading(false)
    }
  }, [cursor])

  return (
    <>
      <NextSeo
        title={`Remote Sales & Marketing jobs`}
        description="The latest and most popular remote sales & marketing jobs around the web. Jobs included from top remote companies. Find your new sales & marketing career on Remotebond."
        canonical={`https://remotebond.com/remote-sales-marketing-jobs`}
        openGraph={{
          url: `https://remotebond.com/remote-sales-marketing-jobs`,
          title: `Remote sales & marketing jobs`,
          description: `The latest and most popular remote sales & marketing jobs around the web. Jobs included from top remote companies. Find your new sales & marketing career on Remotebond.`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: "Remote Sales & Marketing jobs",
          },
        ]}
      />
      <div className="relative overflow-hidden bg-black mb-12">
        <div className="max-w-screen-xl mx-auto text-center py-6 md:py-12 px-4 sm:px-6">
          <div className="flex items-center justify-center">
            <h1 className="text-white font-black text-2xl md:text-4xl my-4">
              Remote Sales &amp; Marketing Jobs
            </h1>
            <a
              href={`https://remotebond.com/remote-sales-marketing-jobs.rss`}
              className="inline-block w-5 h-5 text-white bg-orange-400 rounded-md p-px ml-3 hover:text-white"
              title={`Remote Sales and Marketing Jobs RSS Feed`}
            >
              <svg
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M6 5c7.18 0 13 5.82 13 13M6 11a7 7 0 017 7m-6 0a1 1 0 11-2 0 1 1 0 012 0z"
                />
              </svg>
            </a>
          </div>
          <h2 className="text-base md:text-xl text-rb-gray-4 w-3/4 mx-auto">
            Browse {jobsCount} Remote Sales &amp; Marketing jobs in{" "}
            {date.toLocaleDateString("en-EN", dateOptions)}
          </h2>
          <span className="inline-flex rounded-md shadow-sm mt-8">
            <Link href={`/hire-remotely`} as={`/hire-remotely`}>
              <a
                title="Post a remote job and hire remotely"
                className="inline-flex items-center px-6 py-3 border border-transparent text-base leading-6 font-bold rounded-md text-white bg-rb-green-6 hover:bg-rb-green-5 hover:text-white focus:outline-none focus:border-rb-green-7 focus:shadow-outline-blue active:bg-rb-green-7 transition ease-in-out duration-150"
              >
                Post a job for $25
              </a>
            </Link>
          </span>
        </div>
      </div>

      {/* Filters  */}
      {categories && <FilterBar categories={categories.data} />}

      {cursor.page !== 0 && data && data.data && !isLoading ? (
        <JobsList
          slug="remote-sales-marketing-jobs"
          jobs={data.data}
          loadMoreJobs={loadMoreJobs}
          loadPrevPage={loadPrevPage}
          isLoadingJobs={isLoading}
          isPaginated
          hasPrevPage={cursor.before}
          hasMoreJobs={data.after}
        />
      ) : cursor.page !== 0 ? (
        <Loader />
      ) : null}

      {/* Weird hack to have pre-rendered content, useSWR is acting weird with initialData */}
      {cursor.page === 0 && initialData && (
        <JobsList
          slug="remote-sales-marketing-jobs"
          jobs={initialData.data}
          loadMoreJobs={loadMoreJobs}
          loadPrevPage={loadPrevPage}
          isLoadingJobs={isLoading}
          isPaginated
          hasPrevPage={null}
          hasMoreJobs={initialData.after}
        />
      )}
    </>
  )
}
Example #6
Source File: remote-non-tech-jobs.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
RemoteDesignJobs = ({
  jobsCount,
  initialData,
  initialAfter,
  firstPubDate,
  categories,
  initialPubDate,
}) => {
  const [cursor, setCursor] = useState({
    key: initialAfter,
    date: firstPubDate,
    page: 0,
    before: null,
    isPrevClicked: false,
    isNextClicked: false,
  })
  const [isLoading, setIsLoading] = useState(false)
  const [firstRender, setFirstRender] = useState(true)

  const newJobs = () => {
    if (cursor.isPrevClicked) {
      return `/api/jobs/prev?key=${cursor.before}&d=${cursor.prevDate}`
    }

    if (!cursor.date && !cursor.isPrevClicked) {
      return `/api/jobs/next`
    } else {
      return `/api/jobs/next?key=${cursor.key}&d=${cursor.date}`
    }
  }

  const { data, mutate } = useSWR(!isLoading ? newJobs : null, fetcher)

  let date = new Date()
  let dateOptions = {
    year: "numeric",
    month: "long",
  }

  const loadMoreJobs = () => {
    setCursor({
      key: data.after[2]
        ? data.after[2]["@ref"].id
        : data.after[1]
        ? data.after[1]["@ref"].id
        : null,
      prevDate: data.before[0], //data.data[0].data.pub_date,
      date: data.after[0], //data.data.slice(-1)[0].data.pub_date,
      page: cursor.page + 1,
      before:
        data && data.before && data.before[2]
          ? data.before[2]["@ref"].id
          : data.before[1]
          ? data.before[1]["@ref"].id
          : null,
      isPrevClicked: false,
      isNextClicked: true,
    })
    setIsLoading(true)
  }

  const loadPrevPage = () => {
    setCursor({
      key:
        data.after && data.after[2]
          ? data.after[2]["@ref"].id
          : data.after && data.after[1]
          ? data.after[1]["@ref"].id
          : null,
      prevDate: data.before[0], //data.data[0].data.pub_date,
      date: data.after ? data.after[0] : null, //data.data.slice(-1)[0].data.pub_date,
      page: cursor.page - 1,
      before:
        data.before && data.before[2]
          ? data.before[2]["@ref"].id
          : data.before[1]
          ? data.before[1]["@ref"].id
          : null,
      isPrevClicked: true,
      isNextClicked: false,
    })
  }

  // Fetch new jobs on state change
  useEffect(() => {
    if (firstRender) {
      setFirstRender(false)
    } else {
      mutate()
      setIsLoading(false)
    }
  }, [cursor])

  return (
    <>
      <NextSeo
        title={`Remote non tech jobs`}
        description="The latest and most popular remote non tech jobs around the web. Jobs included from top remote companies. Find your new non tech careeer on Remotebond."
        canonical={`https://remotebond.com/remote-non-tech-jobs`}
        openGraph={{
          url: `https://remotebond.com/remote-non-tech-jobs`,
          title: `Remote non tech jobs`,
          description: `The latest and most popular remote non tech jobs around the web. Jobs included from top remote companies. Find your new non tech career on Remotebond.`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: "Remote Non Tech jobs",
          },
        ]}
      />
      <div className="relative overflow-hidden bg-black mb-12">
        <div className="max-w-screen-xl mx-auto text-center py-6 md:py-12 px-4 sm:px-6">
          <div className="flex items-center justify-center">
            <h1 className="text-white font-black text-2xl md:text-4xl my-4">
              Remote Non Tech Jobs
            </h1>
            <a
              href={`https://remotebond.com/remote-non-tech-jobs.rss`}
              className="inline-block w-5 h-5 text-white bg-orange-400 rounded-md p-px ml-3 hover:text-white"
              title={`Remote Non Tech Jobs RSS Feed`}
            >
              <svg
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M6 5c7.18 0 13 5.82 13 13M6 11a7 7 0 017 7m-6 0a1 1 0 11-2 0 1 1 0 012 0z"
                />
              </svg>
            </a>
          </div>
          <h2 className="text-base md:text-xl text-rb-gray-4 w-3/4 mx-auto">
            Browse {jobsCount} Remote Non Tech jobs in{" "}
            {date.toLocaleDateString("en-EN", dateOptions)}
          </h2>
          <span className="inline-flex rounded-md shadow-sm mt-8">
            <Link href={`/hire-remotely`} as={`/hire-remotely`}>
              <a
                title="Post a remote job and hire remotely"
                className="inline-flex items-center px-6 py-3 border border-transparent text-base leading-6 font-bold rounded-md text-white bg-rb-green-6 hover:bg-rb-green-5 hover:text-white focus:outline-none focus:border-rb-green-7 focus:shadow-outline-blue active:bg-rb-green-7 transition ease-in-out duration-150"
              >
                Post a job for $25
              </a>
            </Link>
          </span>
        </div>
      </div>

      {/* Filters  */}
      {categories && <FilterBar categories={categories.data} />}

      {cursor.page !== 0 && data && data.data && !isLoading ? (
        <JobsList
          slug="remote-non-tech-jobs"
          jobs={data.data}
          loadMoreJobs={loadMoreJobs}
          loadPrevPage={loadPrevPage}
          isLoadingJobs={isLoading}
          isPaginated
          hasPrevPage={cursor.before}
          hasMoreJobs={data.after}
        />
      ) : cursor.page !== 0 ? (
        <Loader />
      ) : null}

      {/* Weird hack to have pre-rendered content, useSWR is acting weird with initialData */}
      {cursor.page === 0 && initialData && (
        <JobsList
          slug="remote-non-tech-jobs"
          jobs={initialData.data}
          loadMoreJobs={loadMoreJobs}
          loadPrevPage={loadPrevPage}
          isLoadingJobs={isLoading}
          isPaginated
          hasPrevPage={null}
          hasMoreJobs={initialData.after}
        />
      )}
    </>
  )
}
Example #7
Source File: index.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
RemoteDesignJobs = (props) => {
  const categories = props.categories.data
  const softwareDevJobs = props.softwareDevJobs.data
  const customerSupportJobs = props.customerSupportJobs.data
  const salesMarketingJobs = props.salesMarketingJobs.data
  const designJobs = props.designJobs.data
  const nonTechJobs = props.nonTechJobs.data
  let date = new Date()
  let dateOptions = {
    year: "numeric",
    month: "long",
  }
  return (
    <>
      <NextSeo
        title={`Remote Software Development, Marketing, Design and more jobs`}
        description={`The latest and most popular remote jobs around the web. Jobs included from top remote companies. Find your new remote career on Remotebond.`}
        canonical={`https://remotebond.com/remote-jobs`}
        openGraph={{
          url: `https://remotebond.com/remote-jobs`,
          title: `Remote Software Development, Marketing, Design and more jobs`,
          description: `The latest and most popular remote jobs around the web. Jobs included from top remote companies. Find your new remote career on Remotebond.`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: "Remote Jobs",
          },
        ]}
      />
      <div className="relative overflow-hidden bg-black mb-12">
        <div className="max-w-screen-xl mx-auto text-center py-6 md:py-12 px-4 sm:px-6">
          <h1 className="text-white font-black text-2xl md:text-4xl my-4">
            Remote Jobs
          </h1>
          <h2 className="text-base md:text-xl text-rb-gray-4 w-3/4 mx-auto">
            Browse Remote Jobs for Software Development, Sales & Marketing,
            Design, Customer Support and more in{" "}
            {date.toLocaleDateString("en-EN", dateOptions)}
          </h2>
          <span className="inline-flex rounded-md shadow-sm mt-8">
            <Link href={`/hire-remotely`} as={`/hire-remotely`}>
              <a
                title="Hire remotely with Remotebond"
                className="inline-flex items-center px-6 py-3 border border-transparent text-base leading-6 font-bold rounded-md text-white bg-rb-green-6 hover:bg-rb-green-5 hover:text-white focus:outline-none focus:border-rb-green-7 focus:shadow-outline-blue active:bg-rb-green-7 transition ease-in-out duration-150"
              >
                Post a job for $25
              </a>
            </Link>
          </span>
        </div>
      </div>

      {/* Filters  */}
      <FilterBar categories={categories} />

      {/* Posting group */}
      <JobsList
        title="Software Development"
        slug="remote-dev-jobs"
        jobs={softwareDevJobs}
      />
      <JobsList
        title="Customer Support"
        slug="remote-customer-support-jobs"
        jobs={customerSupportJobs}
      />
      <JobsList
        title="Sales & Marketing"
        slug="remote-sales-marketing-jobs"
        jobs={salesMarketingJobs}
      />
      <JobsList title="Design" slug="remote-design-jobs" jobs={designJobs} />
      <JobsList
        title="Non Tech"
        slug="remote-non-tech-jobs"
        jobs={nonTechJobs}
      />
    </>
  )
}
Example #8
Source File: index.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
JobsPage = ({ job, slug }) => {
  const salarayAmount = randomInt(40000, 80000)
  const router = useRouter()

  if (router.isFallback) {
    return (
      <div className="max-w-screen-xl mx-auto py-10 px-4 sm:px-6">
        <h1>Loading...</h1>
      </div>
    )
  }

  let newDate = new Date(job.pub_date)
  newDate.setMonth(newDate.getMonth() + 1)
  const jobExpireDate = new Date(newDate).toISOString()
  const saniztizedAndStripped = sanitizeHtml(strip_tags(job.description))
  const isEmail = validateEmail(job.apply_url)
  return (
    <>
      <NextSeo
        title={`Remote ${job.title} job at ${job.company_name}`}
        description={`${saniztizedAndStripped.substr(0, 140)}...`}
        canonical={`https://remotebond.com/remote-jobs/${slug}`}
        openGraph={{
          url: `https://remotebond.com/remote-jobs/${slug}`,
          title: `Remote ${job.title} job at ${job.company_name}`,
          description: `${saniztizedAndStripped.substr(0, 140)}...`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: "Remote Jobs",
            item: "https://remotebond.com/remote-jobs",
          },
          {
            position: 3,
            name: `Remote ${job.title} job at ${job.company_name}`,
          },
        ]}
      />
      <JobPostingJsonLd
        datePosted={job.pub_date}
        description={strip_tags(job.description)}
        hiringOrganization={{
          name: job.company_name,
          sameAs: null,
        }}
        jobLocation={{
          streetAddress: "Anywhere",
          addressLocality: "Anywhere",
          addressRegion: "Anywhere",
          postalCode: "Anywhere",
          addressCountry: "Anywhere",
        }}
        title={job.title}
        baseSalary={{
          currency: "USD",
          value: salarayAmount,
          unitText: "YEAR",
        }}
        employmentType="FULL_TIME"
        jobLocationType="TELECOMMUTE"
        validThrough={jobExpireDate}
      />
      <JobHeader
        title={job.title}
        company={job.company_name}
        applyUrl={job.apply_url}
        location={job.location}
        isEmail={isEmail}
      />

      <Breadcrumbs jobTitle={job.title} category={job.primary_category} />
      <div className="max-w-screen-xl mx-auto py-10 px-4 sm:px-6">
        <div className="w-full md:w-3/4">
          <div
            className="prose prose-sm sm:prose lg:prose-lg xl:prose-xl jobDescription__container py-6"
            dangerouslySetInnerHTML={{ __html: job.description }}
          ></div>

          <div className="flex justify-center mb-8">
            <span className="inline-flex rounded-md shadow-sm">
              {!isEmail ? (
                <a
                  href={`${job.apply_url}?utm_source=remotebond.com&ref=remotebond.com`}
                  target="_blank"
                  className="inline-flex items-center px-6 py-3 border border-transparent text-base leading-6 font-bold rounded-md text-white bg-rb-green-6 hover:bg-rb-green-5 hover:text-white focus:outline-none focus:border-rb-green-7 focus:shadow-outline-blue active:bg-rb-green-7 transition ease-in-out duration-150"
                >
                  Apply for this job
                </a>
              ) : (
                <a
                  href={`mailto:${job.apply_url}?subject=Application for ${job.title} via Remotebond`}
                  target="_blank"
                  className="inline-flex items-center px-6 py-3 border border-transparent text-base leading-6 font-bold rounded-md text-white bg-rb-green-6 hover:bg-rb-green-5 hover:text-white focus:outline-none focus:border-rb-green-7 focus:shadow-outline-blue active:bg-rb-green-7 transition ease-in-out duration-150"
                >
                  Apply for this job
                </a>
              )}
            </span>
          </div>

          {/* Notification */}
          <div className="rounded-md bg-blue-50 p-4">
            <div className="flex">
              <div className="flex-shrink-0">
                <svg
                  className="h-5 w-5 text-blue-400"
                  viewBox="0 0 20 20"
                  fill="currentColor"
                >
                  <path
                    fillRule="evenodd"
                    d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z"
                    clipRule="evenodd"
                  />
                </svg>
              </div>
              <div className="ml-3">
                <p className="text-xs leading-5 text-blue-700">
                  Keep in mind you never have to pay to apply. Never pay for
                  equipment or training. The basic rule is; NEVER pay for
                  anything when applying. When talking to the job poster, make
                  sure you're talking to someone from the actual company. By
                  clicking the apply button you will leave Remotebond to the
                  external application website.
                </p>
                <br />
                <p className="text-xs leading-5 text-blue-700">
                  Remotebond accepts no liability or responsibility as a
                  consequence of any reliance upon information on there
                  (external sites) or here.
                </p>
              </div>
            </div>
          </div>
        </div>
      </div>
    </>
  )
}
Example #9
Source File: remote-dev-jobs.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
RemoteDevJobsPage = ({
  jobsCount,
  initialData,
  initialAfter,
  firstPubDate,
  categories,
  initialPubDate,
}) => {
  const [cursor, setCursor] = useState({
    key: initialAfter,
    date: firstPubDate,
    page: 0,
    before: null,
    isPrevClicked: false,
    isNextClicked: false,
  })
  const [isLoading, setIsLoading] = useState(false)
  const [firstRender, setFirstRender] = useState(true)

  const newJobs = () => {
    if (cursor.isPrevClicked) {
      return `/api/jobs/prev?key=${cursor.before}&d=${cursor.prevDate}`
    }

    if (!cursor.date && !cursor.isPrevClicked) {
      return `/api/jobs/next`
    } else {
      return `/api/jobs/next?key=${cursor.key}&d=${cursor.date}`
    }
  }

  const { data, mutate } = useSWR(!isLoading ? newJobs : null, fetcher)

  let date = new Date()
  let dateOptions = {
    year: "numeric",
    month: "long",
  }

  const loadMoreJobs = () => {
    setCursor({
      key: data.after[2]
        ? data.after[2]["@ref"].id
        : data.after[1]
        ? data.after[1]["@ref"].id
        : null,
      prevDate: data.before[0], //data.data[0].data.pub_date,
      date: data.after[0], //data.data.slice(-1)[0].data.pub_date,
      page: cursor.page + 1,
      before:
        data && data.before && data.before[2]
          ? data.before[2]["@ref"].id
          : data.before[1]
          ? data.before[1]["@ref"].id
          : null,
      isPrevClicked: false,
      isNextClicked: true,
    })
    setIsLoading(true)
  }

  const loadPrevPage = () => {
    setCursor({
      key:
        data.after && data.after[2]
          ? data.after[2]["@ref"].id
          : data.after && data.after[1]
          ? data.after[1]["@ref"].id
          : null,
      prevDate: data.before[0], //data.data[0].data.pub_date,
      date: data.after ? data.after[0] : null, //data.data.slice(-1)[0].data.pub_date,
      page: cursor.page - 1,
      before:
        data.before && data.before[2]
          ? data.before[2]["@ref"].id
          : data.before[1]
          ? data.before[1]["@ref"].id
          : null,
      isPrevClicked: true,
      isNextClicked: false,
    })
  }

  // Fetch new jobs on state change
  useEffect(() => {
    if (firstRender) {
      setFirstRender(false)
    } else {
      mutate()
      setIsLoading(false)
    }
  }, [cursor])

  return (
    <>
      <NextSeo
        title={`Remote software developer / programming jobs`}
        description="The latest and most popular remote software developer / programming jobs around the web. Jobs included from top remote companies. Find your new software developer / programming career on Remotebond."
        canonical={`https://remotebond.com/remote-dev-jobs`}
        openGraph={{
          url: `https://remotebond.com/remote-dev-jobs`,
          title: `Remote software developer / programming jobs`,
          description: `The latest and most popular remote software developer / programming jobs around the web. Jobs included from top remote companies. Find your new software developer / programming career on Remotebond.`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: "Remote Software Developer / Programming jobs",
          },
        ]}
      />
      <div className="relative overflow-hidden bg-black mb-12">
        <div className="max-w-screen-xl mx-auto text-center py-6 md:py-12 px-4 sm:px-6">
          <div className="flex items-center justify-center">
            <h1 className="text-white font-black text-2xl md:text-4xl my-4">
              Remote Software Development Jobs
            </h1>
            <a
              href={`https://remotebond.com/remote-dev-jobs.rss`}
              className="inline-block w-5 h-5 text-white bg-orange-400 rounded-md p-px ml-3 hover:text-white"
              title={`Remote Software Development Jobs RSS Feed`}
            >
              <svg
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M6 5c7.18 0 13 5.82 13 13M6 11a7 7 0 017 7m-6 0a1 1 0 11-2 0 1 1 0 012 0z"
                />
              </svg>
            </a>
          </div>
          <h2 className="text-base md:text-xl text-rb-gray-4 w-3/4 mx-auto">
            Browse {jobsCount} Remote Software Development jobs in{" "}
            {date.toLocaleDateString("en-EN", dateOptions)}
          </h2>
          <span className="inline-flex rounded-md shadow-sm mt-8">
            <Link href={`/hire-remotely`} as={`/hire-remotely`}>
              <a
                title="Post a remote job and hire remotely"
                className="inline-flex items-center px-6 py-3 border border-transparent text-base leading-6 font-bold rounded-md text-white bg-rb-green-6 hover:bg-rb-green-5 hover:text-white focus:outline-none focus:border-rb-green-7 focus:shadow-outline-blue active:bg-rb-green-7 transition ease-in-out duration-150"
              >
                Post a job for $25
              </a>
            </Link>
          </span>
        </div>
      </div>

      {/* Filters  */}
      {categories && <FilterBar categories={categories.data} />}

      {cursor.page !== 0 && data && data.data && !isLoading ? (
        <JobsList
          slug="remote-dev-jobs"
          jobs={data.data}
          loadMoreJobs={loadMoreJobs}
          loadPrevPage={loadPrevPage}
          isLoadingJobs={isLoading}
          isPaginated
          hasPrevPage={cursor.before}
          hasMoreJobs={data.after}
        />
      ) : cursor.page !== 0 ? (
        <Loader />
      ) : null}

      {/* Weird hack to have pre-rendered content, useSWR is acting weird with initialData */}
      {cursor.page === 0 && initialData && (
        <JobsList
          slug="remote-dev-jobs"
          jobs={initialData.data}
          loadMoreJobs={loadMoreJobs}
          loadPrevPage={loadPrevPage}
          isLoadingJobs={isLoading}
          isPaginated
          hasPrevPage={null}
          hasMoreJobs={initialData.after}
        />
      )}
    </>
  )
}
Example #10
Source File: remote-design-jobs.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
RemoteDesignJobs = ({
  jobsCount,
  initialData,
  initialAfter,
  firstPubDate,
  categories,
  initialPubDate,
}) => {
  const [cursor, setCursor] = useState({
    key: initialAfter,
    date: firstPubDate,
    page: 0,
    before: null,
    isPrevClicked: false,
    isNextClicked: false,
  })
  const [isLoading, setIsLoading] = useState(false)
  const [firstRender, setFirstRender] = useState(true)

  const newJobs = () => {
    if (cursor.isPrevClicked) {
      return `/api/jobs/prev?key=${cursor.before}&d=${cursor.prevDate}`
    }

    if (!cursor.date && !cursor.isPrevClicked) {
      return `/api/jobs/next`
    } else {
      return `/api/jobs/next?key=${cursor.key}&d=${cursor.date}`
    }
  }

  const { data, mutate } = useSWR(!isLoading ? newJobs : null, fetcher)

  let date = new Date()
  let dateOptions = {
    year: "numeric",
    month: "long",
  }

  const loadMoreJobs = () => {
    setCursor({
      key: data.after[2]
        ? data.after[2]["@ref"].id
        : data.after[1]
        ? data.after[1]["@ref"].id
        : null,
      prevDate: data.before[0], //data.data[0].data.pub_date,
      date: data.after[0], //data.data.slice(-1)[0].data.pub_date,
      page: cursor.page + 1,
      before:
        data && data.before && data.before[2]
          ? data.before[2]["@ref"].id
          : data.before[1]
          ? data.before[1]["@ref"].id
          : null,
      isPrevClicked: false,
      isNextClicked: true,
    })
    setIsLoading(true)
  }

  const loadPrevPage = () => {
    setCursor({
      key:
        data.after && data.after[2]
          ? data.after[2]["@ref"].id
          : data.after && data.after[1]
          ? data.after[1]["@ref"].id
          : null,
      prevDate: data.before[0], //data.data[0].data.pub_date,
      date: data.after ? data.after[0] : null, //data.data.slice(-1)[0].data.pub_date,
      page: cursor.page - 1,
      before:
        data.before && data.before[2]
          ? data.before[2]["@ref"].id
          : data.before[1]
          ? data.before[1]["@ref"].id
          : null,
      isPrevClicked: true,
      isNextClicked: false,
    })
  }

  // Fetch new jobs on state change
  useEffect(() => {
    if (firstRender) {
      setFirstRender(false)
    } else {
      mutate()
      setIsLoading(false)
    }
  }, [cursor])

  return (
    <>
      <NextSeo
        title={`Remote design jobs`}
        description="The latest and most popular remote design jobs around the web. Jobs included from top remote companies. Find your new design career on Remotebond."
        canonical={`https://remotebond.com/remote-design-jobs`}
        openGraph={{
          url: `https://remotebond.com/remote-design-jobs`,
          title: `Remote design jobs`,
          description: `The latest and most popular remote design jobs around the web. Jobs included from top remote companies. Find your new design career on Remotebond.`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: "Remote Design jobs",
          },
        ]}
      />
      <div className="relative overflow-hidden bg-black mb-12">
        <div className="max-w-screen-xl mx-auto text-center py-6 md:py-12 px-4 sm:px-6">
          <div className="flex items-center justify-center">
            <h1 className="text-white font-black text-2xl md:text-4xl my-4">
              Remote Design Jobs
            </h1>
            <a
              href={`https://remotebond.com/remote-design-jobs.rss`}
              className="inline-block w-5 h-5 text-white bg-orange-400 rounded-md p-px ml-3 hover:text-white"
              title={`Remote Design Jobs RSS Feed`}
            >
              <svg
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M6 5c7.18 0 13 5.82 13 13M6 11a7 7 0 017 7m-6 0a1 1 0 11-2 0 1 1 0 012 0z"
                />
              </svg>
            </a>
          </div>
          <h2 className="text-base md:text-xl text-rb-gray-4 w-3/4 mx-auto">
            Browse {jobsCount} Remote design jobs in{" "}
            {date.toLocaleDateString("en-EN", dateOptions)}
          </h2>
          <span className="inline-flex rounded-md shadow-sm mt-8">
            <Link href={`/hire-remotely`} as={`/hire-remotely`}>
              <a
                title="Post a remote job and hire remotely"
                className="inline-flex items-center px-6 py-3 border border-transparent text-base leading-6 font-bold rounded-md text-white bg-rb-green-6 hover:bg-rb-green-5 hover:text-white focus:outline-none focus:border-rb-green-7 focus:shadow-outline-blue active:bg-rb-green-7 transition ease-in-out duration-150"
              >
                Post a job for $25
              </a>
            </Link>
          </span>
        </div>
      </div>

      {/* Filters  */}
      {categories && <FilterBar categories={categories.data} />}

      {cursor.page !== 0 && data && data.data && !isLoading ? (
        <JobsList
          slug="remote-design-jobs"
          jobs={data.data}
          loadMoreJobs={loadMoreJobs}
          loadPrevPage={loadPrevPage}
          isLoadingJobs={isLoading}
          isPaginated
          hasPrevPage={cursor.before}
          hasMoreJobs={data.after}
        />
      ) : cursor.page !== 0 ? (
        <Loader />
      ) : null}

      {/* Weird hack to have pre-rendered content, useSWR is acting weird with initialData */}
      {cursor.page === 0 && initialData && (
        <JobsList
          slug="remote-design-jobs"
          jobs={initialData.data}
          loadMoreJobs={loadMoreJobs}
          loadPrevPage={loadPrevPage}
          isLoadingJobs={isLoading}
          isPaginated
          hasPrevPage={null}
          hasMoreJobs={initialData.after}
        />
      )}
    </>
  )
}
Example #11
Source File: remote-customer-support-jobs.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
RemoteCustomerSupportPage = ({
  jobsCount,
  initialData,
  initialAfter,
  firstPubDate,
  categories,
  initialPubDate,
}) => {
  const [cursor, setCursor] = useState({
    key: initialAfter,
    date: firstPubDate,
    page: 0,
    before: null,
    isPrevClicked: false,
    isNextClicked: false,
  })
  const [isLoading, setIsLoading] = useState(false)
  const [firstRender, setFirstRender] = useState(true)

  const newJobs = () => {
    if (cursor.isPrevClicked) {
      return `/api/jobs/prev?key=${cursor.before}&d=${cursor.prevDate}`
    }

    if (!cursor.date && !cursor.isPrevClicked) {
      return `/api/jobs/next`
    } else {
      return `/api/jobs/next?key=${cursor.key}&d=${cursor.date}`
    }
  }

  const { data, mutate } = useSWR(!isLoading ? newJobs : null, fetcher)

  let date = new Date()
  let dateOptions = {
    year: "numeric",
    month: "long",
  }

  const loadMoreJobs = () => {
    setCursor({
      key: data.after[2]
        ? data.after[2]["@ref"].id
        : data.after[1]
        ? data.after[1]["@ref"].id
        : null,
      prevDate: data.before[0], //data.data[0].data.pub_date,
      date: data.after[0], //data.data.slice(-1)[0].data.pub_date,
      page: cursor.page + 1,
      before:
        data && data.before && data.before[2]
          ? data.before[2]["@ref"].id
          : data.before[1]
          ? data.before[1]["@ref"].id
          : null,
      isPrevClicked: false,
      isNextClicked: true,
    })
    setIsLoading(true)
  }

  const loadPrevPage = () => {
    setCursor({
      key:
        data.after && data.after[2]
          ? data.after[2]["@ref"].id
          : data.after && data.after[1]
          ? data.after[1]["@ref"].id
          : null,
      prevDate: data.before[0], //data.data[0].data.pub_date,
      date: data.after ? data.after[0] : null, //data.data.slice(-1)[0].data.pub_date,
      page: cursor.page - 1,
      before:
        data.before && data.before[2]
          ? data.before[2]["@ref"].id
          : data.before[1]
          ? data.before[1]["@ref"].id
          : null,
      isPrevClicked: true,
      isNextClicked: false,
    })
  }

  // Fetch new jobs on state change
  useEffect(() => {
    if (firstRender) {
      setFirstRender(false)
    } else {
      mutate()
      setIsLoading(false)
    }
  }, [cursor])

  return (
    <>
      <NextSeo
        title={`Remote customer support jobs`}
        description="The latest and most popular remote customer support jobs around the web. Jobs included from top remote companies. Find your new customer support career on Remotebond."
        canonical={`https://remotebond.com/remote-customer-support-jobs`}
        openGraph={{
          url: `https://remotebond.com/remote-customer-support-jobs`,
          title: `Remote customer support jobs`,
          description: `The latest and most popular remote customer support jobs around the web. Jobs included from top remote companies. Find your new customer support career on Remotebond.`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: "Remote Customer Support Jobs",
          },
        ]}
      />
      <div className="relative overflow-hidden bg-black mb-12">
        <div className="max-w-screen-xl mx-auto text-center py-6 md:py-12 px-4 sm:px-6">
          <div className="flex items-center justify-center">
            <h1 className="text-white font-black text-2xl md:text-4xl my-4">
              Remote Customer Support Jobs
            </h1>
            <a
              href={`https://remotebond.com/remote-customer-support-jobs.rss`}
              className="inline-block w-5 h-5 text-white bg-orange-400 rounded-md p-px ml-3 hover:text-white"
              title={`Remote Customer Support Jobs RSS Feed`}
            >
              <svg
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M6 5c7.18 0 13 5.82 13 13M6 11a7 7 0 017 7m-6 0a1 1 0 11-2 0 1 1 0 012 0z"
                />
              </svg>
            </a>
          </div>
          <h2 className="text-base md:text-xl text-rb-gray-4 w-3/4 mx-auto">
            Browse {jobsCount} Remote Customer Support jobs in{" "}
            {date.toLocaleDateString("en-EN", dateOptions)}
          </h2>
          <span className="inline-flex rounded-md shadow-sm mt-8">
            <Link href={`/hire-remotely`} as={`/hire-remotely`}>
              <a
                title="Post a remote job and hire remotely"
                className="inline-flex items-center px-6 py-3 border border-transparent text-base leading-6 font-bold rounded-md text-white bg-rb-green-6 hover:bg-rb-green-5 hover:text-white focus:outline-none focus:border-rb-green-7 focus:shadow-outline-blue active:bg-rb-green-7 transition ease-in-out duration-150"
              >
                Post a job for $25
              </a>
            </Link>
          </span>
        </div>
      </div>

      {/* Filters  */}
      {categories && <FilterBar categories={categories.data} />}

      {cursor.page !== 0 && data && data.data && !isLoading ? (
        <JobsList
          slug="remote-customer-support-jobs"
          jobs={data.data}
          loadMoreJobs={loadMoreJobs}
          loadPrevPage={loadPrevPage}
          isLoadingJobs={isLoading}
          isPaginated
          hasPrevPage={cursor.before}
          hasMoreJobs={data.after}
        />
      ) : cursor.page !== 0 ? (
        <Loader />
      ) : null}

      {/* Weird hack to have pre-rendered content, useSWR is acting weird with initialData */}
      {cursor.page === 0 && initialData && (
        <JobsList
          slug="remote-customer-support-jobs"
          jobs={initialData.data}
          loadMoreJobs={loadMoreJobs}
          loadPrevPage={loadPrevPage}
          isLoadingJobs={isLoading}
          isPaginated
          hasPrevPage={null}
          hasMoreJobs={initialData.after}
        />
      )}
    </>
  )
}
Example #12
Source File: [tag].js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
JobsPage = ({
  jobs,
  slug,
  initialData,
  initialAfter,
  firstPubDate,
  initialPubDate,
}) => {
  const router = useRouter()
  if (router.isFallback) {
    return (
      <div className="max-w-screen-xl mx-auto py-10 px-4 sm:px-6">
        <h1>Loading...</h1>
      </div>
    )
  }

  const [cursor, setCursor] = useState({
    key: initialAfter,
    date: firstPubDate,
    page: 0,
    before: null,
    isPrevClicked: false,
    isNextClicked: false,
  })
  const [isLoading, setIsLoading] = useState(false)
  const [firstRender, setFirstRender] = useState(true)

  const newJobs = () => {
    if (cursor.isPrevClicked) {
      return `/api/jobs/prev?key=${cursor.before}&d=${cursor.prevDate}&tag=${slug}`
    }

    if (!cursor.date && !cursor.isPrevClicked) {
      return `/api/jobs/next?tag=${slug}`
    } else {
      return `/api/jobs/next?key=${cursor.key}&d=${cursor.date}&tag=${slug}`
    }
  }

  const { data, mutate } = useSWR(!isLoading ? newJobs : null)

  const tagStr = slug.replace(/-/g, " ")
  let date = new Date()
  let dateOptions = {
    year: "numeric",
    month: "long",
  }
  const loadMoreJobs = () => {
    setCursor({
      key: data.after[2]
        ? data.after[2]["@ref"].id
        : data.after[1]
        ? data.after[1]["@ref"].id
        : null,
      prevDate: data.before[0], //data.data[0].data.pub_date,
      date: data.after[0], //data.data.slice(-1)[0].data.pub_date,
      page: cursor.page + 1,
      before:
        data && data.before && data.before[2]
          ? data.before[2]["@ref"].id
          : data.before[1]
          ? data.before[1]["@ref"].id
          : null,
      isPrevClicked: false,
      isNextClicked: true,
    })
    setIsLoading(true)
  }

  const loadPrevPage = () => {
    setCursor({
      key:
        data.after && data.after[2]
          ? data.after[2]["@ref"].id
          : data.after && data.after[1]
          ? data.after[1]["@ref"].id
          : null,
      prevDate: data.before[0], //data.data[0].data.pub_date,
      date: data.after ? data.after[0] : null, //data.data.slice(-1)[0].data.pub_date,
      page: cursor.page - 1,
      before:
        data.before && data.before[2]
          ? data.before[2]["@ref"].id
          : data.before[1]
          ? data.before[1]["@ref"].id
          : null,
      isPrevClicked: true,
      isNextClicked: false,
    })
  }

  // Fetch new jobs on state change
  useEffect(() => {
    if (firstRender) {
      setFirstRender(false)
    } else {
      mutate()
      setIsLoading(false)
    }
  }, [cursor])
  return (
    <>
      <NextSeo
        title={`Remote ${tagStr} jobs`}
        description={`The latest and most popular remote ${tagStr} jobs around the web. Jobs included from top remote companies. Find your new ${tagStr} career on Remotebond.`}
        canonical={`https://remotebond.com/remote-${slug}-jobs`}
        openGraph={{
          url: `https://remotebond.com/remote-${slug}-jobs`,
          title: `Remote ${tagStr} jobs`,
          description: `The latest and most popular remote ${tagStr} jobs around the web. Jobs included from top remote companies. Find your new ${tagStr} career on Remotebond.`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: `Remote ${tagStr} jobs`,
          },
        ]}
      />
      <div className="relative overflow-hidden bg-black mb-12">
        <div className="max-w-screen-xl mx-auto text-center py-6 md:py-12 px-4 sm:px-6">
          <h1 className="text-white font-black text-2xl md:text-4xl my-4">
            Remote <span className="capitalize">{tagStr}</span> Jobs
          </h1>
          <h2 className="text-base md:text-xl text-rb-gray-4 w-3/4 mx-auto">
            Browse {initialData.length} remote {tagStr} jobs in{" "}
            {date.toLocaleDateString("en-EN", dateOptions)}
          </h2>
          <span className="inline-flex rounded-md shadow-sm mt-8">
            <Link href={`/hire-remotely`} as={`/hire-remotely`}>
              <a
                title="Hire remotely with Remotebond"
                className="inline-flex items-center px-6 py-3 border border-transparent text-base leading-6 font-bold rounded-md text-white bg-rb-green-6 hover:bg-rb-green-5 hover:text-white focus:outline-none focus:border-rb-green-7 focus:shadow-outline-blue active:bg-rb-green-7 transition ease-in-out duration-150"
              >
                Post a job for $25
              </a>
            </Link>
          </span>
        </div>
      </div>

      <div className="max-w-screen-xl w-full mx-auto py-10 px-4 sm:px-6">
        {cursor.page !== 0 && data && data.data && !isLoading ? (
          <JobsList
            slug={`remote-${slug}-jobs`}
            jobs={data.data}
            loadMoreJobs={loadMoreJobs}
            loadPrevPage={loadPrevPage}
            isLoadingJobs={isLoading}
            isPaginated
            hasPrevPage={cursor.before}
            hasMoreJobs={data.after}
          />
        ) : cursor.page !== 0 ? (
          <Loader />
        ) : null}

        {/* Weird hack to have pre-rendered content, useSWR is acting weird with initialData */}
        {cursor.page === 0 && initialData && (
          <JobsList
            slug={`remote-${slug}-jobs`}
            jobs={initialData.data}
            loadMoreJobs={loadMoreJobs}
            loadPrevPage={loadPrevPage}
            isLoadingJobs={isLoading}
            isPaginated
            hasPrevPage={null}
            hasMoreJobs={initialData.after}
          />
        )}
      </div>
    </>
  )
}
Example #13
Source File: [companySlug].js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
RemoteCompaniesIndexPage = (props) => {
  const router = useRouter()
  const {
    company: { data: company },
    jobs: { data: jobs },
  } = props

  let date = new Date()
  let dateOptions = {
    year: "numeric",
    month: "long",
  }

  if (router.isFallback) {
    return (
      <div className="max-w-screen-xl mx-auto py-10 px-4 sm:px-6">
        <h1>Loading...</h1>
      </div>
    )
  }

  if (!company) {
    return (
      <>
        <Head>
          <meta name="robots" content="noindex" />
        </Head>
        <DefaultErrorPage statusCode={404} />
      </>
    )
  } else {
    return (
      <>
        <NextSeo
          title={`${company.name} hiring remotely`}
          description={`${company.name} is hiring remotely. ${
            jobs.length
          } remote jobs open in ${date.toLocaleDateString(
            "en-EN",
            dateOptions
          )}`}
          canonical={`https://remotebond.com/remote-companies/${company.slug}`}
          openGraph={{
            url: `https://remotebond.com/remote-companies/${company.slug}`,
            title: `${company.name} hiring remotely`,
            description: `${company.name} is hiring remotely. ${
              jobs.length
            } remote jobs open in ${date.toLocaleDateString(
              "en-EN",
              dateOptions
            )}`,
          }}
        />
        <BreadcrumbJsonLd
          itemListElements={[
            {
              position: 1,
              name: "remotebond.com",
              item: "https://remotebond.com",
            },
            {
              position: 2,
              name: "Remote Companies",
              item: "https://remotebond.com/remote-companies",
            },
            {
              position: 3,
              name: `${company.name}`,
            },
          ]}
        />
        <div className="relative overflow-hidden bg-black">
          <div className="max-w-screen-xl mx-auto text-center py-6 md:py-12 px-4 sm:px-6">
            <h1 className="text-white font-black text-2xl md:text-4xl my-4">
              {company.name}
            </h1>
            <h2 className="text-base md:text-xl text-rb-gray-4 w-3/4 mx-auto">
              {company.name} is hiring remotely and currently has {jobs.length}{" "}
              remote job {jobs.length === 1 ? "position" : "positions"} open in{" "}
              {date.toLocaleDateString("en-EN", dateOptions)}
            </h2>
          </div>
        </div>

        <div className="w-full max-w-screen-xl mx-auto py-10 px-4 sm:px-6">
          {jobs && jobs.length && (
            <JobsList title={`Remote jobs at ${company.name}`} jobs={jobs} />
          )}
        </div>
      </>
    )
  }
}
Example #14
Source File: register.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
RegisterPage = () => {
  const { mutateUser } = useUser({
    redirectTo: "/",
    redirectIfFound: true,
  })
  const [errorMessage, setErrorMessage] = useState("")

  const { handleSubmit, register, watch, errors } = useForm()

  const onSubmit = handleSubmit(async (formData) => {
    if (errorMessage) setErrorMessage("")

    try {
      await mutateUser(
        fetchJson("/api/signup", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(formData),
        })
      )
    } catch (error) {
      setErrorMessage(error.data.message)
    }
  })

  return (
    <>
      <NextSeo
        title={`Register for a Remotebond remote profile and join the future of remote work.`}
        description="Register now and join the future of remote work on Remotebond."
        canonical={`https://remotebond.com/register`}
        openGraph={{
          url: `https://remotebond.com/register`,
          title: `Register for a Remotebond remote profile and join the future of remote work.`,
          description: `Register now and join the future of remote work on Remotebond.`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: "Register",
          },
        ]}
      />
      <div className="flex flex-col flex-1">
        <div className="relative overflow-hidden bg-black">
          <div className="max-w-screen-xl mx-auto py-16 px-4 sm:px-6 lg:py-12 lg:px-8">
            <div>
              <h1 className="text-center text-3xl leading-9 font-extrabold text-white">
                Register your account
              </h1>
            </div>
          </div>
        </div>
        <div className="flex flex-1 items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
          <div className="max-w-md w-full">
            {Object.keys(errors).length !== 0 && (
              <Alert
                title={`There ${
                  Object.keys(errors).length > 1 ? "are" : "is"
                } ${Object.keys(errors).length} ${
                  Object.keys(errors).length > 1 ? "errors" : "error"
                } with your submission`}
                message={`Please fix the marked ${
                  Object.keys(errors).length > 1 ? "fields" : "field"
                } and try submitting your job post again`}
              />
            )}
            {errorMessage && <Alert title="Errors" message={errorMessage} />}
            <form onSubmit={onSubmit} className="mt-8">
              <input type="hidden" name="remember" value="true" />
              <div className="rounded-md shadow-sm">
                <div>
                  <input
                    aria-label="Username"
                    name="username"
                    type="username"
                    required
                    className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5"
                    placeholder="Username"
                    ref={register({ required: "Username is required" })}
                  />
                </div>
                <div className="-mt-px">
                  <input
                    aria-label="Email address"
                    name="email"
                    type="email"
                    required
                    className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5"
                    placeholder="Email address"
                    ref={register({ required: "Email is required" })}
                  />
                </div>
                <div className="-mt-px">
                  <input
                    aria-label="Password"
                    name="password"
                    type="password"
                    required
                    className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5"
                    placeholder="Password"
                    ref={register({ required: "Password is required" })}
                  />
                </div>
                <div className="-mt-px">
                  <input
                    aria-label="Password"
                    name="password2"
                    type="password"
                    required
                    className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5"
                    placeholder="Repeat password"
                    ref={register({
                      validate: (value) =>
                        value === watch("password") || "Passwords do not match",
                    })}
                  />
                </div>
              </div>

              <div className="mt-6 flex items-center justify-between">
                <div className="flex items-center">
                  <input
                    id="remember_me"
                    type="checkbox"
                    className="form-checkbox h-4 w-4 text-blue-600 transition duration-150 ease-in-out"
                  />
                  <label
                    htmlFor="remember_me"
                    className="ml-2 block text-sm leading-5 text-gray-900"
                  >
                    Remember me
                  </label>
                </div>

                <div className="text-sm leading-5">
                  <a
                    href="#"
                    className="font-medium text-blue-600 hover:text-blue-500 focus:outline-none focus:underline transition ease-in-out duration-150"
                  >
                    Forgot your password?
                  </a>
                </div>
              </div>

              <div className="mt-6">
                <button
                  type="submit"
                  className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-blue-600 hover:bg-blue-500 focus:outline-none focus:border-blue-700 focus:shadow-outline-blue active:bg-blue-700 transition duration-150 ease-in-out"
                >
                  <span className="absolute left-0 inset-y-0 flex items-center pl-3">
                    <svg
                      className="h-5 w-5 text-blue-500 group-hover:text-blue-400 transition ease-in-out duration-150"
                      fill="currentColor"
                      viewBox="0 0 20 20"
                    >
                      <path
                        fillRule="evenodd"
                        d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
                        clipRule="evenodd"
                      />
                    </svg>
                  </span>
                  Sign up
                </button>
              </div>
              <div className="mt-6 text-center">
                <Link as={`/login`} href={`/login`}>
                  <a className="font-medium text-blue-600 hover:text-blue-500 focus:outline-none focus:underline transition ease-in-out duration-150">
                    Already have an account?
                  </a>
                </Link>
              </div>
            </form>
          </div>
        </div>
      </div>
    </>
  )
}
Example #15
Source File: login.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
LoginPage = () => {
  const { mutateUser } = useUser({
    redirectTo: "/",
    redirectIfFound: true,
  })

  const router = useRouter()
  const [errorMessage, setErrorMessage] = useState("")

  const { handleSubmit, register, watch, errors } = useForm()

  const onSubmit = handleSubmit(async (formData) => {
    if (errorMessage) setErrorMessage("")

    try {
      await mutateUser(
        fetchJson("/api/login", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(formData),
        })
      )
    } catch (error) {
      console.error(error)
      setErrorMessage(error.message)
    }
  })

  return (
    <>
      <NextSeo
        title={`Login for a Remotebond remote profile and join the future of remote work.`}
        description="Login now and join the future of remote work on Remotebond."
        canonical={`https://remotebond.com/login`}
        openGraph={{
          url: `https://remotebond.com/login`,
          title: `Login for a Remotebond remote profile and join the future of remote work.`,
          description: `Login now and join the future of remote work on Remotebond.`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: "Login",
          },
        ]}
      />
      <div className="flex flex-col flex-1">
        <div className="relative overflow-hidden bg-black">
          <div className="max-w-screen-xl mx-auto py-16 px-4 sm:px-6 lg:py-12 lg:px-8">
            <div>
              <h1 className="text-center text-3xl leading-9 font-extrabold text-white">
                Login to Remotebond
              </h1>
            </div>
          </div>
        </div>
        <div className="flex flex-1 items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
          <div className="max-w-md w-full">
            <form onSubmit={onSubmit} className="mt-8">
              <input type="hidden" name="remember" value="true" />
              <div className="rounded-md shadow-sm">
                <div>
                  <input
                    aria-label="Email address"
                    name="email"
                    type="email"
                    required
                    className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5"
                    placeholder="Email address"
                    ref={register({ required: "Email is required" })}
                  />
                </div>
                <div className="-mt-px">
                  <input
                    aria-label="Password"
                    name="password"
                    type="password"
                    required
                    className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5"
                    placeholder="Repeat password"
                    ref={register({ required: "Password is required" })}
                  />
                </div>
              </div>

              <div className="mt-6 flex items-center justify-between">
                <div className="flex items-center">
                  <input
                    id="remember_me"
                    type="checkbox"
                    className="form-checkbox h-4 w-4 text-blue-600 transition duration-150 ease-in-out"
                  />
                  <label
                    htmlFor="remember_me"
                    className="ml-2 block text-sm leading-5 text-gray-900"
                  >
                    Remember me
                  </label>
                </div>

                <div className="text-sm leading-5">
                  <a
                    href="#"
                    className="font-medium text-blue-600 hover:text-blue-500 focus:outline-none focus:underline transition ease-in-out duration-150"
                  >
                    Forgot your password?
                  </a>
                </div>
              </div>
              <div className="mt-6">
                <button
                  type="submit"
                  className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-blue-600 hover:bg-blue-500 focus:outline-none focus:border-blue-700 focus:shadow-outline-blue active:bg-blue-700 transition duration-150 ease-in-out"
                >
                  <span className="absolute left-0 inset-y-0 flex items-center pl-3">
                    <svg
                      className="h-5 w-5 text-blue-500 group-hover:text-blue-400 transition ease-in-out duration-150"
                      fill="currentColor"
                      viewBox="0 0 20 20"
                    >
                      <path
                        fillRule="evenodd"
                        d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z"
                        clipRule="evenodd"
                      />
                    </svg>
                  </span>
                  Login
                </button>
              </div>
              <div className="mt-6 text-center">
                <Link as={`/register`} href={`/register`}>
                  <a className="font-medium text-blue-600 hover:text-blue-500 focus:outline-none focus:underline transition ease-in-out duration-150">
                    Don't have an account?
                  </a>
                </Link>
              </div>
            </form>
          </div>
        </div>
      </div>
    </>
  )
}
Example #16
Source File: frequently-asked-questions.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
FaqPage = () => {
  return (
    <>
      <NextSeo
        title={`Remotebond - Frequently Asked Questions`}
        description="Remotebond - Frequently asked questions about remote work, remote jobs and regular information about Remotebond"
        canonical={`https://remotebond.com/frequently-asked-questions`}
        openGraph={{
          url: `https://remotebond.com/frequently-asked-questions`,
          title: `Remotebond - Frequently Asked Questions`,
          description: `Remotebond - Frequently asked questions about remote work, remote jobs and regular information about Remotebond`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: "Frequently Asked Questions",
          },
        ]}
      />
      <FAQPageJsonLd
        mainEntity={[
          {
            questionName: "What is Remotebond?",
            acceptedAnswerText:
              "Remotebond is a global community of remote workers. It is a place where knowledge is shared to shape the future of remote work. Whether you’re a remote company looking to hire or a worker looking for your next remote opportunity, I have created a platform that provides a variety of jobs with new listings added daily. With Remotebond, I aim to bring talented freelancers and remote workers to companies from all over the world, making the world of work barrier-free.",
          },
          {
            questionName: "How do I post a job on Remotebond?",
            acceptedAnswerText:
              "To post a job on Remotebond Click on 'Post a job' in the header. Fill out the required information in the form, and preview your job posting. If everything looks okay, fill out your payment information and press 'Post job'. After a successfull payment, you will receive a receipt containing information about your job posting. Keep this receipt, as it contains information about your posting and how to edit it.",
          },
          {
            questionName: "Can I edit my job post after it's live?",
            acceptedAnswerText:
              "It is possible to edit your post after it's live. However keep in mind that you cannot edit your job title after it's live. Everything else is editable. To edit your post, look for the email receipt you received after posting your job. In this email you will find the link to edit your post.",
          },
          {
            questionName: "How much does it cost to post a job?",
            acceptedAnswerText:
              "The current price to post a base job post is $25. Prices will increase after the initial launch period. You can choose to highlight your post, this will ensure that your post stands out from the rest and gets more attention. The extra price for this is $100. It is also possible to add a company logo to your job post. This makes sure people recognize your company and it also helps to get more attention to your job post. The extra price for this is $25",
          },
          {
            questionName: "How long will my post be live?",
            acceptedAnswerText:
              "Your post will be online for 30 days. After that your post will be archived and visitors will not be able to apply for the position anymore.",
          },
          {
            questionName: "Will my post auto bump after 30 days?",
            acceptedAnswerText:
              "Currently your post will not auto-bump and you are not able to bump it yourself. If you need your post to bump, please contact me, and I can bump it manually for you.",
          },
          {
            questionName: "How can I register a profile on Remotebond?",
            acceptedAnswerText:
              "Click on the 'Register account' button on the homepage or go directly to the register page to create a profile on Remotebond.",
          },
        ]}
      />
      <div className="relative overflow-hidden bg-black mb-12">
        <div className="max-w-screen-xl mx-auto py-16 px-4 sm:px-6 lg:py-24 lg:px-8">
          <h1 className="text-4xl leading-10 font-display font-semibold text-white text-center md:text-5xl md:leading-none">
            Frequently Asked Questions
          </h1>
        </div>
      </div>
      <div className="max-w-screen-xl mx-auto pt-4 pb-16 px-4 sm:px-6 lg:px-8">
        <div>
          <div className="mb-12">
            <h2 className="text-xl leading-7 font-bold text-gray-900">
              What is Remotebond?
            </h2>
            <p className="text-base leading-6 text-gray-500">
              Remotebond is a global community of remote workers. It is a place
              where knowledge is shared to shape the future of remote work.
            </p>
            <p className="mt-4 text-base leading-6 text-gray-500">
              Whether you’re a remote company looking to hire or a worker
              looking for your next remote opportunity, I have created a
              platform that provides a variety of jobs with new listings added
              daily.
            </p>
            <p className="mt-4 text-base leading-6 text-gray-500">
              With Remotebond, I (
              <a
                href="https://www.twitter.com/erhankaradeniz"
                title="Erhan Karadeniz on Twitter"
                className="font-medium"
              >
                Erhan Karadeniz
              </a>
              ) aim to bring talented freelancers and remote workers to
              companies from all over the world, making the world of work
              barrier-free.
            </p>
          </div>
          <dl className="md:grid md:grid-cols-2 md:gap-8">
            <div>
              <div>
                <dt className="text-lg leading-6 font-medium text-gray-900">
                  <h2>How do I post a job on Remotebond?</h2>
                </dt>
                <dd className="mt-2">
                  <p className="text-base leading-6 text-gray-500">
                    Are you looking for a remote worker? Let Remotebond help
                    you!
                  </p>
                  <p className="mt-4 text-base leading-6 text-gray-500">
                    <strong>To post a job on Remotebond</strong>
                  </p>
                  <ol className="list-decimal pl-4 mt-4 text-base leading-6 text-gray-500">
                    <li>
                      Click on "Post a job" in the header or{" "}
                      <Link as={`/hire-remotely`} href={`/hire-remotely`}>
                        <a
                          className="font-medium"
                          title="Post a remote job on Remotebond"
                        >
                          click here
                        </a>
                      </Link>
                    </li>
                    <li className="mt-1">
                      Fill out the required information in the form, and preview
                      your job posting.
                    </li>
                    <li className="mt-1">
                      If everything looks okay, fill out your payment
                      information and press "Post job".
                    </li>
                    <li className="mt-1">
                      After a successfull payment, you will receive a receipt
                      containing information about your job posting. Keep this
                      receipt, as it contains information about your posting and
                      how to edit it.
                    </li>
                  </ol>
                  <p className="mt-4 text-base leading-6 text-gray-500">
                    Secure payment guaranteed by{" "}
                    <a
                      href="https://www.stripe.com"
                      title="Remotebond payments by Stripe"
                      className="font-medium"
                    >
                      Stripe
                    </a>{" "}
                    over HTTPS
                  </p>
                </dd>
              </div>
              <div className="mt-12">
                <dt className="text-lg leading-6 font-medium text-gray-900">
                  <h2>Can I edit my job post after it's live?</h2>
                </dt>
                <dd className="mt-2">
                  <p className="text-base leading-6 text-gray-500">
                    It is possible to edit your post after it's live. However
                    keep in mind that you cannot edit your job title after it's
                    live. Everything else is editable.
                  </p>
                  <p className="mt-4 text-base leading-6 text-gray-500">
                    To edit your post, look for the email receipt you received
                    after posting your job. In this email you will find the link
                    to edit your post. If you have not received this email,{" "}
                    <a
                      href="https://www.twitter.com/erhankaradeniz"
                      title="Contact Erhan Karadeniz"
                      className="font-medium"
                    >
                      contact
                    </a>{" "}
                    me and I will be happy to help you out.
                  </p>
                </dd>
              </div>
            </div>
            <div className="mt-12 sm:mt-0">
              <div id="team-pricing">
                <dt className="text-lg leading-6 font-medium text-gray-900">
                  <h2>How much does it cost to post a job?</h2>
                </dt>
                <dd className="mt-2">
                  <p className="text-base leading-6 text-gray-500">
                    The current price to post a <strong>base</strong> job post
                    is <strong>$25</strong>. Prices will increase after the
                    initial launch period.
                  </p>
                  <p className="mt-4 text-base leading-6 text-gray-500">
                    <strong>Make your job stand out!</strong>
                  </p>
                  <p className="text-base leading-6 text-gray-500">
                    You can choose to highlight your post, this will ensure that
                    your post stands out from the rest and gets more attention.
                    The extra price for this is <strong>$100</strong>
                  </p>
                  <p className="mt-4 text-base leading-6 text-gray-500">
                    <strong>Add your logo</strong>
                  </p>
                  <p className="text-base leading-6 text-gray-500">
                    It is also possible to add a company logo to your job post.
                    This makes sure people recognize your company and it also
                    helps to get more attention to your job post. The extra
                    price for this is <strong>$25</strong>
                  </p>
                </dd>
              </div>
              <div className="mt-12">
                <dt className="text-lg leading-6 font-medium text-gray-900">
                  <h2>How long will my post be live?</h2>
                </dt>
                <dd className="mt-2">
                  <p className="text-base leading-6 text-gray-500">
                    Your post will be online for 30 days. After that your post
                    will be archived and visitors will not be able to apply for
                    the position anymore.
                  </p>
                </dd>
              </div>
              <div>
                <dt className="mt-12 text-lg leading-6 font-medium text-gray-900">
                  <h2>Will my post auto bump after 30 days?</h2>
                </dt>
                <dd className="mt-2">
                  <p className="text-base leading-6 text-gray-500">
                    Currently your post will not auto-bump and you are not able
                    to bump it yourself. If you need your post to bump, please{" "}
                    <a
                      href="https://www.twitter.com/erhankaradeniz"
                      title="Contact Erhan Karadeniz"
                      className="font-medium"
                    >
                      contact
                    </a>{" "}
                    me, and I can bump it manually for you.
                  </p>
                  <p className="mt-4 text-base leading-6 text-gray-500">
                    Keep in mind that bumping your job post comes with extra
                    costs. In the future you will be able to bump your post by
                    yourself.
                  </p>
                </dd>
              </div>
              <div>
                <dt className="mt-12 text-lg leading-6 font-medium text-gray-900">
                  <h2>How can I register a profile on Remotebond?</h2>
                </dt>
                <dd className="mt-2">
                  <p className="text-base leading-6 text-gray-500">
                    Click on the "Register account" button on the{" "}
                    <Link as={`/`} href={`/`}>
                      <a title="Remotebond homepage" className="font-medium">
                        homepage
                      </a>
                    </Link>{" "}
                    or go directly to the{" "}
                    <Link as={`/register`} href={`/register`}>
                      <a title="Remotebond homepage" className="font-medium">
                        register
                      </a>
                    </Link>{" "}
                    page to create a profile on Remotebond.
                  </p>
                </dd>
              </div>
            </div>
          </dl>
        </div>
      </div>
    </>
  )
}
Example #17
Source File: index.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
ForumIndexPage = (props) => {
  const { user } = useUser()
  const [isSlideOverOpen, setIsSlideOverOpen] = useState(false)
  const [isLoginModalOpen, setIsLoginModalOpen] = useState(false)

  // Forum threads data
  const forumTopics = props.forumTopics.data
  const forumCategories = props.forumCategories.data
  forumTopics.sort(function (a, b) {
    // Turn your strings into dates, and then subtract them
    // to get a value that is either negative, positive, or zero.
    return new Date(b.topic.data.created_at) - new Date(a.topic.data.created_at)
  })
  const openSlideOver = () => {
    user?.isLoggedIn
      ? setIsSlideOverOpen(!isSlideOverOpen)
      : setIsLoginModalOpen(!isLoginModalOpen)
  }

  return (
    <>
      <NextSeo
        title={`Remotebond Forum a hub for everything related to remote work`}
        description="The Remotebond Forum is a how-to content hub for all things remote work."
        canonical={`https://remotebond.com/forum`}
        openGraph={{
          url: `https://remotebond.com/forum`,
          title: `Remotebond Forum a hub for everything related to remote work`,
          description: `The Remotebond Forum is a how-to content hub for all things remote work.`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: "Forum",
          },
        ]}
      />
      <div className="relative overflow-hidden bg-black mb-12 z-10">
        <div className="max-w-screen-xl mx-auto py-16 px-4 sm:px-6 lg:py-12 lg:px-8">
          <div>
            <h1 className="text-center text-3xl leading-10 font-extrabold text-white">
              Remote Work Forum
            </h1>
            <h2 className="text-rb-gray-4 text-center w-full">
              The Remotebond Forum is a how-to content hub for all things remote
              work. From best practices for job seekers, tools, resources and
              news to hiring tips and processes, the Remotebond forum is meant
              to be community-driven documentation on how to get remote work
              right.
            </h2>
          </div>
          <div className="flex justify-center items-center mt-8 space-y-4 sm:space-y-0 sm:space-x-4 flex-col sm:flex-row">
            <span className="inline-flex rounded-md shadow-sm">
              <button
                onClick={openSlideOver}
                className="inline-flex items-center px-6 py-3 border border-transparent text-base leading-6 font-bold rounded-md text-white bg-rb-green-6 hover:bg-rb-green-5 hover:text-white focus:outline-none focus:border-rb-green-7 focus:shadow-outline-blue active:bg-rb-green-7 transition ease-in-out duration-150"
              >
                Create topic
              </button>
            </span>
          </div>
        </div>
      </div>
      <div className="max-w-screen-xl z-10 w-full mx-auto py-4 px-4 sm:px-6 flex space-x-0 md:space-x-8 flex-col md:flex-row">
        <Sidebar categories={forumCategories} />
        <TopicsList topics={forumTopics} />
      </div>
      <CreateTopicSliderOver
        isOpen={isSlideOverOpen}
        handleClose={() => setIsSlideOverOpen(!isSlideOverOpen)}
        categories={forumCategories}
      />
      <LoginModal
        isModalOpen={isLoginModalOpen}
        handleClose={() => setIsLoginModalOpen(!isLoginModalOpen)}
      />
    </>
  )
}
Example #18
Source File: [slug].js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
ForumTopicPage = (props) => {
  const router = useRouter()
  const {
    topic: { data: topic, ref: topic_ref },
    author: { data: author },
    category: { data: category },
    comments: { data: comments },
  } = props.topic
  const defaultValues = { topic_comment: "" }
  const { user } = useUser()
  const { handleSubmit, register, errors, watch, control, setValue } = useForm({
    defaultValues,
  })

  const isCommentEmpty = watch("topic_comment")

  // Date manipulations
  const pubDate = new Date(topic.created_at)
  const pubDateOptions = {
    weekday: "long",
    year: "numeric",
    month: "long",
    day: "numeric",
  }

  const modules = {
    toolbar: [
      ["bold", "italic", "underline", "strike", "blockquote"],
      [{ list: "ordered" }, { list: "bullet" }],
      ["link"],
      ["clean"],
    ],
    clipboard: {
      // toggle to add extra line breaks when pasting HTML:
      matchVisual: false,
    },
  }
  const formats = [
    "bold",
    "italic",
    "underline",
    "strike",
    "blockquote",
    "list",
    "bullet",
    "indent",
    "link",
  ]

  // Setup category coloring
  let activeTextColor, activeBgColor
  switch (category.color) {
    case "green":
      activeTextColor = "text-green-800"
      activeBgColor = "bg-green-100"
      break
    case "teal":
      activeTextColor = "text-teal-800"
      activeBgColor = "bg-teal-100"
      break
    case "pink":
      activeTextColor = "text-pink-800"
      activeBgColor = "bg-pink-100"
      break
    case "yellow":
      activeTextColor = "text-yellow-800"
      activeBgColor = "bg-yellow-100"
      break
    case "blue":
      activeTextColor = "text-blue-800"
      activeBgColor = "bg-blue-100"
      break
    default:
      activeTextColor = "text-indigo-800"
      activeBgColor = "bg-indigo-100"
  }

  const shareArticle = () => {
    console.log("Sharing article")
  }

  const onSubmit = async (values, e) => {
    e.preventDefault()

    const commentResponse = await fetch(
      `${window.location.origin}/api/forum/comment/new`,
      {
        method: "post",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          topic_comment: values.topic_comment,
          topic_ref: topic_ref["@ref"].id,
        }),
      }
    )
    commentResponse.ok && router.reload()
  }

  let strippedDescription = topic.content.replace(/(<([^>]+)>)/gi, "")

  return (
    <>
      <NextSeo
        title={`${topic.title}`}
        description={`${strippedDescription.substring(0, 110)}...`}
        canonical={`https://remotebond.com/forum/${category.slug}/${topic.slug}`}
        openGraph={{
          url: `https://remotebond.com/forum/${category.slug}/${topic.slug}`,
          title: `${topic.title}`,
          description: `${strippedDescription.substring(0, 110)}...`,
        }}
      />
      <BreadcrumbJsonLd
        itemListElements={[
          {
            position: 1,
            name: "remotebond.com",
            item: "https://remotebond.com",
          },
          {
            position: 2,
            name: "Forum",
          },
        ]}
      />
      <div className="relative overflow-hidden bg-black mb-12">
        <div className="max-w-screen-xl mx-auto py-16 px-4 sm:px-6 lg:py-12 lg:px-8">
          <div>
            <h1 className="text-center text-3xl mb-1 font-extrabold text-white">
              {topic.title}
            </h1>
            <h2 className="text-rb-gray-4 text-center w-full">
              {`This question was asked by`}
              <Link href={`/u/${author.username}`}>
                <a
                  className="mx-2 text-white hover:underline"
                  title={`${author.username} remote worker profile on Remotebond`}
                >
                  {author.username}
                </a>
              </Link>
              {`in the`}
              <span
                className={`px-2 inline-flex text-xs leading-5 font-semibold rounded-full mx-2 ${activeBgColor} ${activeTextColor}`}
              >
                {category.title}
              </span>
              {`category on`}
              {` `}
              {pubDate.toLocaleDateString("en-US", pubDateOptions)}
            </h2>
          </div>
        </div>
      </div>
      <div className="max-w-screen-xl w-full mx-auto pt-4 pb-12 px-4 sm:px-6 flex flex-col">
        <div>
          <div>
            <div className="mb-1">
              <span className="text-sm text-rb-gray-4">
                Posted by{" "}
                <Link
                  href={`/u/${author.username}`}
                >{`${author.username}`}</Link>
              </span>
            </div>
            <div
              className="topic_questionContainer text-rb-gray-8"
              dangerouslySetInnerHTML={{ __html: topic.content }}
            ></div>
          </div>

          {/* Actions bar */}
          <div className="flex my-5">
            <div
              className={`mr-6 flex items-center text-sm leading-5 text-rb-gray-5`}
            >
              <svg
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
                className={`flex-shrink-0 mr-1.5 h-5 w-5 text-rb-gray-4`}
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"
                />
              </svg>
              {`${comments.length} comments`}
            </div>
            <div className={`mr-6`}>
              <button
                className="flex items-center text-sm leading-5 text-rb-gray-5 hover:text-blue-600 group"
                onClick={shareArticle}
              >
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke="currentColor"
                  className={`flex-shrink-0 mr-1.5 h-5 w-5 text-rb-gray-4 group-hover:text-blue-600`}
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth={2}
                    d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z"
                  />
                </svg>
                {`Share`}
              </button>
            </div>
          </div>
        </div>
        {topic.isLocked && (
          <div className="flex flex-col items-center justify-center py-16">
            <span className="text-blue-600">
              <svg
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
                className="h-8 w-8"
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  strokeWidth={2}
                  d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636"
                />
              </svg>
            </span>
            <p className="text-xl font-medium">Commenting disabled</p>
            <p className="text-rb-gray-4">You cannot comment on this post.</p>
          </div>
        )}
        {/* Only show when a user is logged in */}
        {user?.isLoggedIn && !topic.isLocked && (
          <>
            {/* Post container with editor in it */}
            <div className="border-b border-rb-gray-2 pb-4">
              <p className="text-xs">
                Comment as{" "}
                <Link href={`/u/${user.username}`}>{user.username}</Link>
              </p>
              <form onSubmit={handleSubmit(onSubmit)}>
                <CommentEditor
                  control={control}
                  inputError={errors}
                  modules={modules}
                  formats={formats}
                  inputName={"topic_comment"}
                />
                <div className="mt-4 flex flex-col items-end">
                  {/* // Quill Editor does not empty totally and we need to check for the empty paragraph */}
                  <button
                    disabled={
                      !isCommentEmpty || isCommentEmpty == "<p><br></p>"
                    }
                    className="inline-flex items-center px-4 py-2 border border-transparent text-base leading-6 font-bold rounded-md text-white bg-rb-green-6 hover:bg-rb-green-5 hover:text-white focus:outline-none focus:border-rb-green-7 focus:shadow-outline-blue active:bg-rb-green-7 transition ease-in-out duration-150 disabled:bg-rb-gray-4 disabled:cursor-not-allowed"
                  >
                    Comment
                  </button>
                </div>
              </form>
            </div>

            {/* Comments container  */}
            <div>
              {/* No comments */}
              {!comments.length && (
                <div className="flex flex-col items-center justify-center py-16">
                  <span className="text-blue-600">
                    <svg
                      xmlns="http://www.w3.org/2000/svg"
                      fill="none"
                      viewBox="0 0 24 24"
                      stroke="currentColor"
                      className="h-8 w-8"
                    >
                      <path
                        strokeLinecap="round"
                        strokeLinejoin="round"
                        strokeWidth={2}
                        d="M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z"
                      />
                    </svg>
                  </span>
                  <p className="text-xl font-medium">No Comments Yet</p>
                  <p className="text-rb-gray-4">
                    Be the first to share what you think!
                  </p>
                </div>
              )}

              <div className="flex flex-col pt-8 space-y-6">
                {comments.length > 0 &&
                  comments.map((commentObj, idx) => {
                    const {
                      comment: { data: comment },
                      author: { data: author },
                    } = commentObj
                    return (
                      <Comment key={idx} author={author} comment={comment} />
                    )
                  })}
              </div>
            </div>
          </>
        )}

        {/* Only show this message to a user who's not logged in */}
        {!user?.isLoggedIn && <RegisterNotification />}
      </div>
    </>
  )
}