next-seo#NextSeo JavaScript Examples

The following examples show how to use next-seo#NextSeo. 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: _app.jsx    From neighbor-express with MIT License 6 votes vote down vote up
function CustomSeo() {
	let { state, dispatch } = useContext(CMSContext);
	const title = getCmsRecordFromKey('title', state);
	const openGraph = title
		? {
				title: title.title,
				description: title.body,
		  }
		: null;
	return title ? <NextSeo title={title.title} description={title.body} openGraph={openGraph} /> : null;
}
Example #3
Source File: seo.js    From strapi-starter-next-corporate with MIT License 6 votes vote down vote up
Seo = ({ metadata }) => {
  // Prevent errors if no metadata was set
  if (!metadata) return null

  return (
    <NextSeo
      title={metadata.metaTitle}
      description={metadata.metaDescription}
      openGraph={{
        // Title and description are mandatory
        title: metadata.metaTitle,
        description: metadata.metaDescription,
        // Only include OG image if we have it
        // Careful: if you disable image optimization in Strapi, this will break
        ...(metadata.shareImage && {
          images: Object.values(metadata.shareImage.formats).map((image) => {
            return {
              url: getStrapiMedia(image.url),
              width: image.width,
              height: image.height,
            }
          }),
        }),
      }}
      // Only included Twitter data if we have it
      twitter={{
        ...(metadata.twitterCardType && { cardType: metadata.twitterCardType }),
        // Handle is the twitter username of the content creator
        ...(metadata.twitterUsername && { handle: metadata.twitterUsername }),
      }}
    />
  )
}
Example #4
Source File: seo.js    From stacker.news with MIT License 6 votes vote down vote up
export function SeoSearch ({ sub }) {
  const router = useRouter()
  const subStr = sub ? ` ~${sub}` : ''
  const title = `${router.query.q || 'search'} \\ stacker news${subStr}`
  const desc = `SN${subStr} search: ${router.query.q || ''}`

  return (
    <NextSeo
      title={title}
      description={desc}
      openGraph={{
        title: title,
        description: desc,
        images: [
          {
            url: 'https://stacker.news/api/capture' + router.asPath
          }
        ],
        site_name: 'Stacker News'
      }}
      twitter={{
        site: '@stacker_news',
        cardType: 'summary_large_image'
      }}
    />
  )
}
Example #5
Source File: seo.jsx    From docs with MIT License 6 votes vote down vote up
export function SEO({ title, description, slug = "" }) {
  const titleFormatted = `${title ? title : "Nhost documentation"}`;
  const url = `https://docs.nhost.io/${slug}`;

  return (
    <React.Fragment>
      <NextSeo
        title={titleFormatted}
        description={description}
        canonical={url}
        openGraph={{
          url: url,
          title: titleFormatted,
          description: description,
        }}
      />
    </React.Fragment>
  );
}
Example #6
Source File: Header.jsx    From ui with MIT License 6 votes vote down vote up
Header = (props) => {
  const {
    experimentId, experimentData, title, extra,
  } = props;
  const experiment = useSelector((state) => state?.experiments[experimentId]);
  const experimentName = experimentData?.experimentName || experiment?.name;

  const truncateText = (text) => (
    (text && text.length > 28) ? `${text.substr(0, 27)}…` : text
  );

  return (
    <>
      <NextSeo
        title={experimentData ? `${title} · ${truncateText(experimentName)}` : title}
      />

      <PageHeader
        className={integrationTestConstants.classes.PAGE_HEADER}
        title={title}
        style={{ width: '100%', paddingTop: '10px', paddingBottom: '10px' }}
        extra={(
          <Space size='large'>
            <Space>
              <HelpButton />
              <FeedbackButton />
              <ReferralButton />
              {extra}
            </Space>
            <UserButton />
          </Space>
        )}
      />
    </>
  );
}
Example #7
Source File: Seo.js    From mailmask with GNU Affero General Public License v3.0 6 votes vote down vote up
Seo = ({ title, description, publishedTime }) => (
  <NextSeo
    title={title || defaultTitle}
    titleTemplate={title ? '%s | Mailmask' : defaultTitle}
    description={description || `${defaultTitle}. Unlimited, free temporary email addresses, all forwarding to your real email address. Beat spam, protect your privacy.`}
    openGraph={{
      type: 'website',
      locale: 'en_GB',
      site_name: 'Mailmask',
      article: {
        publishedTime: publishedTime ? new Date(publishedTime).toISOString() : '2020-05-31T11:10:51.498Z',
      },
      images: [
        {
          url: 'https://pbs.twimg.com/profile_banners/1275361568511922176/1592904999/1500x500',
          width: 1500,
          height: 500,
          alt: 'Mailmask - easily stop unwanted email',
        },
      ]
    }}
    twitter={{
      handle: '@hiddentao',
      site: '@mskhq',
      cardType: 'summary_large_image',
    }}
  />
)
Example #8
Source File: BlogSeo.js    From benjamincarlson.io with MIT License 6 votes vote down vote up
BlogSeo = ({ title, summary, publishedAt, url, image }) => {
    const date = new Date(publishedAt).toISOString()
    const featuredImage = {
        url: `https://benjamincarlson.io${image}`,
        alt: title
    }

    return (
        <>
            <NextSeo
                title={`${title} – Benjamin Carlson`}
                description={summary}
                canonical={url}
                openGraph={{
                    type: 'article',
                    article: {
                        publishedTime: date
                    },
                    url,
                    title,
                    description: summary,
                    images: [featuredImage]
                }}
            />
            <ArticleJsonLd
                authorName="Benjamin Carlson"
                dateModified={date}
                datePublished={date}
                description={summary}
                images={[featuredImage]}
                publisherLogo="/static/favicons/android-chrome-192x192.png"
                publisherName="Benjamin Carlson"
                title={title}
                url={url}
            />
        </>
    )
}
Example #9
Source File: index.jsx    From club-connect with GNU General Public License v3.0 6 votes vote down vote up
Join = () => {
  const [memberJoined, setMemberJoined] = useState(false);

  return (
    <>
      <Head>
        <title>{pageTitle}</title>
      </Head>

      <NextSeo
        title={pageTitle}
        openGraph={{
          title: pageTitle,
          url: 'https://bccompsci.club/join',
        }}
      />

      {!memberJoined ? (
        <JoinForm setMemberJoined={setMemberJoined} />
      ) : (
        <JoinSuccess />
      )}
    </>
  );
}
Example #10
Source File: SEO.js    From tambouille with MIT License 6 votes vote down vote up
PageSeo = ({ description, url, title = null }) => {
  return (
    <NextSeo
      title={title ? `${title} | ${siteMetadata.title}` : siteMetadata.title}
      description={description}
      canonical={url}
      openGraph={{
        url,
        title,
        description,
      }}
    />
  )
}
Example #11
Source File: global.jsx    From NextBook with MIT License 6 votes vote down vote up
export default function GlobalLayout({ title, part, description, children }) {
  const { projectTitle, projectURL, projectDescription } = config
  const htmlTitle = part ? `${title} - ${part}` : title

  return (
    <>
      <NextSeo
        title={`${htmlTitle} | ${projectTitle}`}
        description={description ? description : projectDescription}
        openGraph={{
          type: 'website',
          url: projectURL,
          title: title,
          description: description
        }}
      />

      <Head>
        <meta
          content='width=device-width, initial-scale=1.0, maximum-scale=5.0'
          name='viewport'
        />
        <link rel='icon' href='/favicon.ico' />
        <link rel='icon' href='/icon.svg' type='image/svg+xml' />
        <link rel='apple-touch-icon' href='/512.png' />
        <link rel='manifest' href='/manifest.json' />
      </Head>

      <header className='z-40 md:shadow-md bg-gray-200 dark:bg-gray-800 fixed w-screen top-0 h-10 md:h-14 font-medium'>
        <NavBar />
      </header>

      <div className='content-wrapper mt-10 md:mt-14 flex xl:container xl:mx-auto'>
        <SideBar />
        <div className='md-wrapper flex md:ml-56 xl:ml-64'>{children}</div>
      </div>
    </>
  )
}
Example #12
Source File: about.jsx    From club-connect with GNU General Public License v3.0 6 votes vote down vote up
About = (props) => {
  return (
    <>
      <Head>
        <title>{pageTitle}</title>
      </Head>

      <NextSeo
        title={pageTitle}
        openGraph={{
          title: pageTitle,
          url: 'https://bccompsci.club/about',
        }}
      />

      <div>
        <TopSection />
        <WhoWeAreSection />
        <WhatWeDoSection />
        <TeamSection />
        <Ending width={props.width} />
      </div>
    </>
  );
}
Example #13
Source File: SEO.js    From tambouille with MIT License 5 votes vote down vote up
BlogSeo = ({ summary, date, lastmod, url, title, tags, images = [] }) => {
  const publishedAt = new Date(date).toISOString()
  const modifiedAt = new Date(lastmod || date).toISOString()
  let imagesArr =
    images.length === 0
      ? [siteMetadata.socialBanner]
      : typeof images === 'string'
      ? [images]
      : images

  const featuredImages = imagesArr.map((img) => ({
    url: `${siteMetadata.siteUrl}${img}`,
    alt: title ?? siteMetadata.title,
  }))

  return (
    <>
      <NextSeo
        title={title ? `${title} | ${siteMetadata.title}` : siteMetadata.title}
        description={summary}
        canonical={url}
        openGraph={{
          type: 'article',
          article: {
            publishedTime: publishedAt,
            modifiedTime: modifiedAt,
            authors: [`${siteMetadata.siteUrl}/about`],
            tags,
          },
          url,
          title: title ?? siteMetadata.title,
          description: summary,
          images: featuredImages,
        }}
        additionalMetaTags={[
          {
            name: 'twitter:image',
            content: featuredImages[0].url,
          },
        ]}
      />
      <ArticleJsonLd
        authorName={siteMetadata.author}
        dateModified={modifiedAt}
        datePublished={publishedAt}
        description={summary}
        images={featuredImages}
        publisherName={siteMetadata.author}
        title={title ?? siteMetadata.title}
        url={url}
      />
    </>
  )
}
Example #14
Source File: seo.js    From stacker.news with MIT License 5 votes vote down vote up
// for a sub we need
// item seo
// index page seo
// recent page seo

export default function Seo ({ sub, item, user }) {
  const router = useRouter()
  const pathNoQuery = router.asPath.split('?')[0]
  const defaultTitle = pathNoQuery.slice(1)
  const snStr = `stacker news${sub ? ` ~${sub}` : ''}`
  let fullTitle = `${defaultTitle && `${defaultTitle} \\ `}stacker news`
  let desc = "It's like Hacker News but we pay you Bitcoin."
  if (item) {
    if (item.title) {
      fullTitle = `${item.title} \\ ${snStr}`
    } else if (item.root) {
      fullTitle = `reply on: ${item.root.title} \\ ${snStr}`
    }
    // at least for now subs (ie the only one is jobs) will always have text
    if (item.text) {
      desc = RemoveMarkdown(item.text)
      if (desc) {
        desc = desc.replace(/\s+/g, ' ')
      }
    } else {
      desc = `@${item.user.name} stacked ${item.sats} sats ${item.url ? `posting ${item.url}` : 'with this discussion'}`
    }
    if (item.ncomments) {
      desc += ` [${item.ncomments} comments`
      if (item.boost) {
        desc += `, ${item.boost} boost`
      }
      desc += ']'
    } else if (item.boost) {
      desc += ` [${item.boost} boost]`
    }
  }
  if (user) {
    desc = `@${user.name} has [${user.stacked} stacked, ${user.nitems} posts, ${user.ncomments} comments]`
  }

  return (
    <NextSeo
      title={fullTitle}
      description={desc}
      openGraph={{
        title: fullTitle,
        description: desc,
        images: [
          {
            url: 'https://stacker.news/api/capture' + pathNoQuery
          }
        ],
        site_name: 'Stacker News'
      }}
      twitter={{
        site: '@stacker_news',
        cardType: 'summary_large_image'
      }}
    />
  )
}
Example #15
Source File: index.js    From NextJS-Boilerplate-withAtomicDesign with MIT License 5 votes vote down vote up
render(){
    const { children, title, description, url, images, showSidebar } = this.props;
    return(
    <Fragment>
      <DefaultSeo openGraph={appConfig.openGraph}/>
      <NextSeo 
        title={title}
        description={description}
        openGraph={{
          url,
          title,
          description,
          images
        }}
      />
      <SiteHeader />
        <MainSection>
          <div className="container">
              <div className="row">
                <div className={showSidebar ? 'main-content' : 'full-mainContent'}>{children}</div>
                {showSidebar && <SiteSidebar />}
              </div>
          </div>
        </MainSection>
      <SiteFooter />
      <style jsx global>
        {`
          * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
          }
          .row {
            display:flex;
            flex-wrap:wrap;
          }
          .container {
            width:1020px;
            margin: auto;
          }
          .section-container {
            padding: 40px 0;
          }
          .full-mainContent {
            width:100%;
            padding:14px;
          }
          .main-content {
            width:70%;
            padding:14px;
          }
        `}
      </style>
    </Fragment>
    )
  }
Example #16
Source File: resetpassword.jsx    From club-connect with GNU General Public License v3.0 5 votes vote down vote up
ResetPassword = () => {
  const [resetEmailSent, setResetEmailSent] = useState(false);
  const [passwordResetKey, setPasswordResetKey] = useState(null);

  useEffect(() => {
    const parsedQueryString = queryString.parse(location.search);

    if (parsedQueryString.key) {
      setPasswordResetKey(parsedQueryString.key);
    }
  }, []);

  return (
    <>
      <Head>
        <title>{pageTitle}</title>
      </Head>

      <NextSeo
        title={pageTitle}
        openGraph={{
          title: pageTitle,
          url: 'https://bccompsci.club/resetpassword',
        }}
      />

      <div>
        <section className={`${authStyles.auth} ${authStyles.authBackground}`}>
          <div className={authStyles.flexContainer}>
            <div className={authStyles.container}>
              <h1>Reset Password</h1>
              {passwordResetKey ? (
                <CompleteResetPasswordForm
                  passwordResetKey={passwordResetKey}
                />
              ) : (
                <>
                  {resetEmailSent ? (
                    <ResetEmailSent />
                  ) : (
                    <RequestPasswordResetForm
                      setResetEmailSent={setResetEmailSent}
                    />
                  )}
                </>
              )}
            </div>
          </div>
        </section>
      </div>
    </>
  );
}
Example #17
Source File: index.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 5 votes vote down vote up
IndexPage = (props) => {
  // Jobs Data
  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

  // Forum threads data
  const forumTopics = props.forumTopics.data
  return (
    <>
      <NextSeo canonical={`https://remotebond.com`} />
      {/* Hero Section */}
      <Hero />

      {/* Forum topics scoller */}
      <TopicsScroller topics={forumTopics} />

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

      {/* Posting group */}
      <JobsList
        title="Software Development"
        slug="/remote-dev-jobs"
        jobs={softwareDevJobs}
      />

      <MailchimpSubscribe
        url={_URL}
        render={({ subscribe, status, message }) => (
          <SubscribeEmailForm
            status={status}
            message={message}
            onValidated={(formData) => subscribe(formData)}
          />
        )}
      />

      <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 #18
Source File: Layout.js    From Modtoberfest-Site with MIT License 5 votes vote down vote up
export default function Layout({
  fluid,
  children,
  className,
  title = "Modtoberfest",
  description,
  canonical,
  image,
  url,
  ...props
}) {
  return (
    <>
      <NextSeo
        title={title}
        description={description}
        canonical={`https://modtoberfest.com${canonical || "/"}`}
        openGraph={{
          type: "website",
          title: title,
          url: `https://modtoberfest.com${url || canonical || "/"}`,
          description: description,
          images: [
            {
              url: image || "https://modtoberfest.com/logo/badge-bg-pad.png",
              alt: title + " logo",
            },
          ],
          site_name: "Modtoberfest",
        }}
        twitter={{
          cardType: "summary_large_image",
        }}
      />
      <div className="flex flex-col min-h-screen h-full">
        <NavBar />
        <main className={classNames("md:px-8 md:pt-1", className)}>
          {children}
        </main>
      </div>
    </>
  );
}
Example #19
Source File: _app.js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 5 votes vote down vote up
App = ({ Component, pageProps }) => {
  const router = useRouter()
  useEffect(() => {
    const handleRouteChange = (url) => {
      gtag.pageview(url)
    }
    router.events.on("routeChangeComplete", handleRouteChange)
    return () => {
      router.events.off("routeChangeComplete", handleRouteChange)
    }
  }, [router.events])
  return (
    <>
      <DefaultSeo {...SEO} />
      <NextSeo
        title="Remotebond - Remote jobs in Software Development, Sales and more"
        description="Looking for a remote job? Hire Remote! Remotebond has thousands of remote work jobs as a Developer, Designer, Customer Support Rep, Sales Professional, Marketing Professional, Project Manager and more!"
      />
      <Head>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
        <meta name="msapplication-config" content="/browserconfig.xml" />
        <meta name="theme-color" content="#ffffff" />
        <link
          rel="apple-touch-icon"
          sizes="180x180"
          href="/siteimg/apple-touch-icon.png"
        />
        <link
          rel="icon"
          type="image/png"
          sizes="32x32"
          href="/siteimg/favicon-32x32.png"
        />
        <link
          rel="icon"
          type="image/png"
          sizes="16x16"
          href="/siteimg/favicon-16x16.png"
        />
        <link rel="manifest" href="/site.webmanifest" />
        <link
          rel="mask-icon"
          href="/siteimg/safari-pinned-tab.svg"
          color="#3c99f7"
        />
        <link rel="shortcut icon" href="/siteimg/favicon.ico" />
        <meta name="msapplication-TileColor" content="#3c99f7" />
        <script
          type="application/ld+json"
          dangerouslySetInnerHTML={{
            __html: JSON.stringify({
              "@context": "http://schema.org",
              "@type": "Organization",
              name: "Remotebond",
              url: "https://remotebond.com",
              logo: "https://remotebond.com/siteimg/logo.png",
              sameAs: ["https://twitter.com/remotebond"],
            }),
          }}
        ></script>
      </Head>
      <SWRConfig
        value={{
          fetcher: fetch,
          onError: (err) => {
            console.error(err)
          },
        }}
      >
        <Layout user={pageProps.user}>
          <Component {...pageProps} />
          <NextNprogress color="#1c64f2" options={{ showSpinner: false }} />
        </Layout>
      </SWRConfig>
    </>
  )
}
Example #20
Source File: resources.jsx    From club-connect with GNU General Public License v3.0 5 votes vote down vote up
Resources = () => {
  return (
    <>
      <Head>
        <title>{pageTitle}</title>
      </Head>

      <NextSeo
        title={pageTitle}
        openGraph={{
          title: pageTitle,
          url: 'https://bccompsci.club/resources',
        }}
      />

      <div
        className={`${commonStyles.container} ${commonStyles.text} ${resourcesStyles.resources}`}
      >
        <h1 className={commonStyles.centerElement}>Resources</h1>
        <LearnResources />

        <br />

        <h1 className={commonStyles.centerElement}>Useful Tools</h1>
        <ToolsResources />

        <Alert variant="primary" className={resourcesStyles.contribute}>
          <Alert.Heading>Contribute to this list!</Alert.Heading>
          <p>
            Have any resources you want to share with us? Post them in our
            Discord community under the <code>#resources</code> channel or&nbsp;
            <Alert.Link
              href="https://github.com/bc-compsci-club/bccompsci.club"
              rel="noopener noreferrer"
              target="_blank"
            >
              submit a pull request here
            </Alert.Link>
            !
          </p>
        </Alert>
      </div>
    </>
  );
}
Example #21
Source File: ToolPageForFramework.jsx    From awesome-tools with MIT License 5 votes vote down vote up
export default function ToolPageForFramework(props) {
  const type = types[props.types[0]];
  const framework = frameworks[props.framework];
  const integration = props.integrations?.find(i => i.framework === props.framework);
  const slackMembers = useSlackMembers();

  return (
    <>
      <NextSeo
        title={`${props.title}${type.descriptor} for ${framework.name} developers`}
        description={`${props.title} support in ${framework.name}${integration && ` with ${integration.slugs.npm}`}, examples, tutorials, compatibility, and popularity`}
      />

      <div className="container custom-container mt-lg">
        <main>
          <Header
            logo={props.logo}
            title={props.title}
            framework={framework.name}
            developer={props.developer}
            website={props?.links?.website}
            github={props?.slugs?.github}
            achievement={props?.feature_label}
          />
          <Description description={props.description} />
          <DescriptionCards
            licenses={props.licenses}
            frameworks={props.frameworks}
            languages={props.languages}
            links={props.links}
            slugs={props.slugs}
          />
          {integration && (
            <Integrations integration={integration} />
          )}
          {props.gallery && props.gallery.length !== 0 && (
            <Gallery gallery={props.gallery} link={props?.links?.examples} />
          )}
          {props.github_data && (
            <Popularity
              slugs={props.slugs}
              github={props.github_data}
              positions={props.positions}
              percentages={props.percentages}
            />
          )}
          {props.content && props.content.length > 0 && (
            <HowToGetStarted content={props.content} />
          )}
          <HowToGetHelp
            slackMembers={slackMembers}
            logo={props.logo}
            name={props.title}
            links={props.links}
            positions={props.positions}
            stackoverflow={
              props?.tags?.stackoverflow
                ? `https://stackoverflow.com/questions/tagged/${encodeURIComponent(
                  props?.tags?.stackoverflow.join(" or "),
                )}`
                : null
            }
            stackoverflow_data={props.stackoverflow_data}
          />
        </main>
      </div>
    </>
  );
}
Example #22
Source File: blog.js    From benjamincarlson.io with MIT License 5 votes vote down vote up
export default function Blog({ posts }) {
    const [searchValue, setSearchValue] = useState('')

    const filteredBlogPosts = posts
        .sort(
            (a, b) =>
                Number(new Date(b.publishedAt)) - Number(new Date(a.publishedAt))
        )
        .filter((frontMatter) =>
            frontMatter.data?.title?.toLowerCase()?.includes(searchValue.toLowerCase()) ||
            frontMatter.data?.summary?.toLowerCase()?.includes(searchValue.toLowerCase())
        )

    return (
        <>
            <NextSeo
                title={title}
                description={description}
                canonical={url}
                openGraph={{
                    url,
                    title,
                    description
                }}
            />
            <Container>
                <Stack
                    as="main"
                    spacing={8}
                    justifyContent="center"
                    alignItems="flex-start"
                    m="0 auto 0 auto"
                    maxWidth="1000px"
                >
                    <Flex
                        flexDirection="column"
                        justifyContent="flex-start"
                        alignItems="flex-start"
                        maxWidth="1000px"
                        px={4}
                        minH="100vh"
                    >
                        <motion.div
                            initial={{ y: -20, opacity: 0 }}
                            animate={{ y: 0, opacity: 1 }}
                            transition={{ duration: .7, delay: .4 }}
                        >
                            <Heading letterSpacing="tight" as="h1" size="2xl" my={4}>
                                Blog ({posts.length} posts)
                            </Heading>
                            <Text mb={2}>I now write for <Link isExternal href="https://www.coffeeclass.io/articles" color="blue.500">coffeeclass.io</Link>. Visit that site to view all my tutorials!</Text>
                            <InputGroup mb={4} mr={4} w="100%">
                                <Input
                                    aria-label="Search by post title or summary"
                                    onChange={(e) => setSearchValue(e.target.value)}
                                    placeholder="Search by post title or summary"
                                />
                                <InputRightElement>
                                    <SearchIcon color="gray.300" />
                                </InputRightElement>
                            </InputGroup>
                            {!filteredBlogPosts.length && 'No posts found.'}
                            {filteredBlogPosts.map((frontMatter, index) => (
                                <BlogPost
                                    key={frontMatter.data.title}
                                    href={posts[index].filePath.replace(/\.mdx?$/, '')}
                                    {...frontMatter.data}
                                />
                            ))}
                        </motion.div>
                    </Flex>
                </Stack>
            </Container>
        </>
    )
}
Example #23
Source File: ToolPage.jsx    From awesome-tools with MIT License 5 votes vote down vote up
export default function ToolPage(props) {
  const type = types[props.types[0]];
  const slackMembers = useSlackMembers();

  return (
    <>
      <NextSeo
        title={`${props.title} — ${type.descriptor}`}
        description={`${props.title} examples, tutorials, compatibility, and popularity`}
      />

      <div className="container custom-container mt-lg">
        <main>
          <Header
            logo={props.logo}
            title={props.title}
            developer={props.developer}
            website={props?.links?.website}
            github={props?.slugs?.github}
            achievement={props?.feature_label}
          />
          <Description based={props.based_on} description={props.description} />
          <DescriptionCards
            licenses={props.licenses}
            frameworks={props.frameworks}
            languages={props.languages}
            links={props.links}
            slugs={props.slugs}
          />
          {props.gallery && props.gallery.length !== 0 && (
            <Gallery gallery={props.gallery} link={props?.links?.examples} />
          )}
          {props.github_data && (
            <Popularity
              slugs={props.slugs}
              github={props.github_data}
              positions={props.positions}
              percentages={props.percentages}
            />
          )}
          {props.integrations?.length > 0 && (
            <Integrations integrations={props.integrations} />
          )}
          {props.content && props.content.length > 0 && (
            <HowToGetStarted content={props.content} />
          )}
          <HowToGetHelp
            slackMembers={slackMembers}
            logo={props.logo}
            name={props.title}
            links={props.links}
            positions={props.positions}
            stackoverflow={
              props?.tags?.stackoverflow
                ? `https://stackoverflow.com/questions/tagged/${encodeURIComponent(
                  props?.tags?.stackoverflow.join(" or "),
                )}`
                : null
            }
            stackoverflow_data={props.stackoverflow_data}
          />
        </main>
      </div>
    </>
  );
}
Example #24
Source File: projects.js    From benjamincarlson.io with MIT License 5 votes vote down vote up
Projects = () => {
    const { colorMode } = useColorMode()

    const colorSecondary = {
        light: 'gray.600',
        dark: 'gray.400'
    }

    const iconColor = {
        light: 'gray.600',
        dark: 'gray.300'
    }

    return (
        <>
            <NextSeo
                title={title}
                description={description}
                canonical={url}
                openGraph={{
                    url,
                    title,
                    description
                }}
            />
            <Container>
                <Flex
                    flexDirection="column"
                    maxWidth="1000px"
                    alignSelf={[null, "center"]}
                >
                    <motion.div
                        initial={{ y: -20, opacity: 0 }}
                        animate={{ y: 0, opacity: 1 }}
                        transition={{ duration: .7, delay: .4 }}
                    >
                        <Heading letterSpacing="tight" my={4} as="h1" size="2xl">
                            Projects
                        </Heading>
                        <Text color={colorSecondary[colorMode]}>Between school, work, youtube, and individual curiosity, I have worked on many projects over the years. If you enjoy or use any of these projects, please consider <Link href="https://github.com/sponsors/bjcarlson42" isExternal color="blue.500">sponsoring me</Link> on GitHub!
                        </Text>
                        <GitHubSponsorCard />
                        <ProjectListFull />
                    </motion.div>
                </Flex>
            </Container>
        </>
    )
}
Example #25
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 #26
Source File: login.jsx    From club-connect with GNU General Public License v3.0 4 votes vote down vote up
LogIn = () => {
  const router = useRouter();
  const dispatch = useDispatch();

  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [formSubmitting, setFormSubmitting] = useState(false);

  useEffect(async () => {
    // Redirect to dashboard if logged in already
    if (getUserIsLoggedIn()) {
      await router.push('/dashboard');
    }
  }, []);

  const handleSubmit = async (e) => {
    e.preventDefault();
    setFormSubmitting(true);

    // Log the user in and retrieve JWT
    const authenticationCredentials = {
      email: email,
      password: password,
    };

    try {
      await axios.post(
        `${API_ROOT}/accounts/login`,
        authenticationCredentials,
        {
          withCredentials: true,
        }
      );
    } catch (err) {
      // err.response might be undefined
      const errStatus = err.response && err.response.status;
      if (errStatus === 401) {
        toastErrorCenter(
          'Your email or password is incorrect. Please check your credentials and try again.'
        );
      } else if (errStatus === 429) {
        toastErrorCenter(
          'You have entered an incorrect email or password too many times. Please try again in an hour.'
        );
      } else {
        toastErrorCenter(
          'An error occurred while trying to log you in. Please try again.'
        );
      }

      setFormSubmitting(false);
      console.error(err);
      return;
    }

    // Set application state and localStorage to be logged in
    await setLoggedIn(dispatch);
    setFormSubmitting(false);

    // Redirect to the appropriate page
    const parsedQueryString = queryString.parse(location.search);
    if (parsedQueryString.returnToPage) {
      router.push(parsedQueryString.returnToPage);
    } else {
      router.push('/dashboard');
    }
  };

  return (
    <>
      <Head>
        <title>{pageTitle}</title>
      </Head>

      <NextSeo
        title={pageTitle}
        openGraph={{
          title: pageTitle,
          url: 'https://bccompsci.club/login',
        }}
      />

      <div>
        <section className={`${authStyles.auth} ${authStyles.authBackground}`}>
          <div className={authStyles.flexContainer}>
            <div className={authStyles.container}>
              <h1>Member Log In</h1>
              <form name="join" id="join-form" onSubmit={handleSubmit}>
                <div className={authStyles.fullWidthField}>
                  <label htmlFor="email">Email Address</label>
                  <input
                    type="email"
                    name="email"
                    id="email"
                    value={email}
                    onChange={(e) => setEmail(e.target.value)}
                    disabled={formSubmitting}
                    required
                  />
                </div>

                <div className={authStyles.fullWidthField}>
                  <label htmlFor="password">Password</label>
                  <input
                    type="password"
                    name="password"
                    id="password"
                    value={password}
                    onChange={(e) => setPassword(e.target.value)}
                    disabled={formSubmitting}
                    required
                  />
                </div>

                <div className={loginFormStyles.resetPassword}>
                  <Link href="/resetpassword">Forgot password?</Link>
                </div>

                <Button
                  classNamePassed={formStyles.cardSubmitButton}
                  type="submit"
                  disabled={formSubmitting}
                  big
                >
                  Log In
                </Button>
              </form>

              <div className={authStyles.alternateAction}>
                <p>
                  <strong>
                    Not a member yet? <Link href="/join">Join Now.</Link>
                  </strong>
                </p>
              </div>
            </div>
          </div>
        </section>
      </div>
    </>
  );
}
Example #27
Source File: index.js    From benjamincarlson.io with MIT License 4 votes vote down vote up
export default function Index() {
  const { colorMode } = useColorMode()

  const colorSecondary = {
    light: 'gray.600',
    dark: 'gray.400'
  }

  const iconColor = {
    light: 'gray.600',
    dark: 'gray.300'
  }

  const linkColor = {
    light: 'blue.400',
    dark: 'blue.600'
  }

  return (
    <>
      <NextSeo
        title={title}
        description={description}
        canonical={url}
        openGraph={{
          url,
          title,
          description
        }}
      />
      <Container>
        <Flex
          flexDirection="column"
          maxWidth="1000px"
          alignSelf={[null, "center"]}
        >
          {/* hero is defined inside of components/Container.js which allows it to have a different bg color without applying p to a bunch of tags */}
          <motion.div
            initial={{ y: -20, opacity: 0 }}
            animate={{ y: 0, opacity: 1 }}
            transition={{ duration: .7, delay: 2 }}
          >
            <Box as="section" mt={10} mb={20}>
              <Heading letterSpacing="tight" mt={8} size="lg" fontWeight={700} as="h2" mb={4}>About Me</Heading>
              <Text color={colorSecondary[colorMode]}>Hi everyone ?, I'm Benjamin Carlson. I go to <Link color="blue.500" href="https://www2.ccsu.edu/" isExternal>Central Connecticut State University</Link> where I study computer science and mathematics. My personal website is where I showcase my projects, writing, statistics, experience, and more. It also serves as a sandbox to play around with new technologies, as seen by the <Link href="https://github.com/bjcarlson42/benjamincarlson.io#overview" color={linkColor[colorMode]} isExternal>evolution</Link> of this website! Feel free to reach out via email or any social media.</Text>
            </Box>

            <Box as="section" mt={10} mb={20}>
              <Heading letterSpacing="tight" mt={8} size="lg" fontWeight={700} as="h2" mb={4}>Featured Projects ?‍?</Heading>
              <SimpleGrid minChildWidth="300px" spacing="40px">
                <ProjectCard
                  title="coffeeclass.io"
                  description="coffeeclass.io is a tutorial website I started to teach programming and computer science skills in a fun and easy to learn manner."
                  repoHref="https://github.com/carlson-technologies/coffeeclass.io"
                  demoHref="https://www.coffeeclass.io?utm_source=website&utm_campaign=benjamincarlson.io"
                  languageColor="#2b7489"
                  language="TypeScript"
                />
                <ProjectCard
                  title="benjamincarlson.io"
                  description="This website is a personal website I built to showcase my projects and experience."
                  repoHref="https://github.com/bjcarlson42/benjamincarlson.io"
                  demoHref="https://benjamincarlson.io"
                  languageColor="#f1e05a"
                  language="JavaScript"
                />
                <ProjectCard
                  title="Word Of The Day App"
                  description="A word of the day app built using Google's Flutter - a cross platform mobile app framework. View current and past words and save your favorites!"
                  repoHref="https://github.com/bjcarlson42/wotd"
                  youtubeId="https://youtu.be/17wMTF_bnnc"
                  languageColor="#00B4AB"
                  language="Dart"
                />
              </SimpleGrid>
            </Box>

            <Box as="section" mt={10} mb={20}>
              <Heading letterSpacing="tight" mt={8} mb={4} size="lg" fontWeight={700} as="h2">Publications ?</Heading>
              <Text color={colorSecondary[colorMode]}>I began writing about programming back in 2019 on my first blog that is no longer alive. Since then I have expanded to different media outlets and covered a variety of topics from programming, to productivity, to business.</Text>
              {/* <Flex align="center" mt={4}> */}
              <SimpleGrid minChildWidth="200px" spacing="20px" my={10}>
                <Flex flexDir="column">
                  <Icon as={YoutubeIcon} color="red.500" fontSize="2xl" mb={2} />
                  <Heading as="h3" size="md" fontWeight={400} mb={2} letterSpacing="tight">
                    <Link href='https://youtube.com/benjamincarlson' color={linkColor[colorMode]} isExternal>YouTube</Link>
                  </Heading>
                  <Text>I started uploading YouTube videos in 2020 when the pandemic started. I mostly upload programming tutorial videos but I also upload developer vlogs and informational videos. I have uploaded (almost) weekly since then and have grown my channel to an audience of over 4k subscribers and 450k views!</Text>
                </Flex>
                <Flex flexDir="column">
                  <Icon as={SiMedium} fontSize="2xl" mb={2} />
                  <Heading as="h3" size="md" fontWeight={400} mb={2} letterSpacing="tight">
                    <Link href='https://benjamincarlson.medium.com' color={linkColor[colorMode]} isExternal>Medium</Link>
                  </Heading>
                  <Text>Medium was the first publication I started. I wrote my <Link color="blue.500" href="https://levelup.gitconnected.com/using-javascript-to-scramble-a-rubiks-cube-306f52908f18" isExternal>first article</Link> in March 2020, and since then I have written about a dozen more articles. Nowadays I write less for Medium and more for coffeeclass.io.</Text>
                </Flex>
                <Flex flexDir="column">
                  <Icon as={FiCoffee} color="yellow.500" fontSize="2xl" mb={2} />
                  <Heading as="h3" size="md" fontWeight={400} mb={2} letterSpacing="tight">
                    <Link href='https://www.coffeeclass.io' color={linkColor[colorMode]} isExternal>coffeeclass.io</Link>
                  </Heading>
                  <Text>Because I enjoyed uploading YouTube videos about programming and writing about programming on Medium, I decided to start my own programming tutorial website, coffeeclass.io. If you are interested in writing about code, see our <Link color="blue.500" href="https://www.coffeeclass.io/contribute/getting-started" isExternal>getting started</Link> page.</Text>
                </Flex>
                <Flex flexDir="column">
                  <Icon as={BsGear} color="gray.500" fontSize="2xl" mb={2} />
                  <Heading as="h3" size="md" fontWeight={400} mb={2} letterSpacing="tight">
                    <Link href='https://www.engineering.coffeeclass.io' color={linkColor[colorMode]} isExternal>engineering.coffeeclass.io</Link>
                  </Heading>
                  <Text>The behind the scenes look at coffeeclass.io. On this site I write about the development of coffeeclass.io. Everything from the current tech stack, future plans, growing pains, and more.</Text>
                </Flex>
              </SimpleGrid>
              {/* </Flex> */}
              <Flex
                mb={4}
                bgColor={useColorModeValue("gray.100", "gray.900")}
                p={[5, 20, 50]}
                borderRadius={3}
                as="blockquote"
                borderLeft="10px solid"
                borderLeftColor={useColorModeValue("blue.400", "blue.700")}
              >
                <Icon as={GrBlockQuote} fontSize={40} color={colorSecondary[colorMode]} mr={4} />
                <Flex flexDir="column">
                  <Text fontSize="xl" fontStyle="italic" color={colorSecondary[colorMode]}>If You Can Think and Speak and Write, You Are Absolutely Deadly.</Text>
                  <Text fontSize="xl" fontWeight="bold" mt={2}>Jordan B. Peterson</Text>
                </Flex>
              </Flex>
            </Box>

            <Todo />
            <TechStack />

            <Box as="section">
              <Text mt={10}>Looks like you've made it to the end of this page... feel free to <Link href="https://youtube.com/benjamincarlson" isExternal color={linkColor[colorMode]}>check out my YouTube channel</Link> or
                visit <Link href="https://www.coffeeclass.io/?utm_source=website&utm_campaign=benjamincarlson.io" isExternal color={linkColor[colorMode]}>coffeeclass.io</Link> where
                you can find even more programming content.
              </Text>
            </Box>
          </motion.div>

        </Flex>
      </Container>
    </>
  )
}
Example #28
Source File: [username].js    From remotebond-remote-jobs with Creative Commons Zero v1.0 Universal 4 votes vote down vote up
UserProfilePage = ({ user }) => {
  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>
    )
  }

  return (
    <>
      <NextSeo
        title={`Remote worker ${user.username} on Remotebond`}
        description={`View the remote worker profile of ${user.username} on Remotebond`}
        canonical={`https://remotebond.com/u/${user.username}`}
        openGraph={{
          url: `https://remotebond.com/u/${user.username}`,
          title: `Remote worker ${user.username} on Remotebond`,
          description: `View the remote worker profile of ${user.username} on Remotebond`,
        }}
      />
      <div className="flex flex-col flex-1">
        <div className="relative overflow-hidden bg-black">
          <div className="max-w-screen-xl mx-auto py-12 px-4 sm:px-6 lg:py-16 lg:px-8">
            <div></div>
          </div>
        </div>
        <div className="flex flex-1 justify-center bg-gray-50 px-4 sm:px-6 lg:px-8">
          <div className="max-w-screen-xl mx-auto w-full -my-14 relative z-10 mb-14">
            <div className="flex flex-col items-center justify-center mb-6">
              {user.profile_image ? (
                <img
                  className="inline-block h-28 w-28 rounded-md mb-2 shadow-md border-white border-2"
                  src={`${user.profile_image}`}
                  alt=""
                />
              ) : (
                <div className="inline-block h-28 w-28 rounded-md mb-2 shadow-md border-white border-2 bg-rb-gray-9 text-rb-gray-5">
                  <svg
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 20 20"
                    fill="currentColor"
                  >
                    <path
                      fill-rule="evenodd"
                      d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z"
                      clip-rule="evenodd"
                    />
                  </svg>
                </div>
              )}
              <div className="max-w-screen-lg text-rb-gray-8 text-center">
                <h1 className="font-medium text-xl">{`@${user.username}`}</h1>
                <p className="">
                  {user.tagline ? user.tagline : "Hello, I'm using Remotebond!"}
                </p>
              </div>
            </div>

            <div className="w-full sm:w-full">
              <div className="bg-white shadow overflow-hidden sm:rounded-lg">
                <div className="px-4 py-5 border-b border-gray-200 sm:px-6">
                  <h3 className="text-lg leading-6 font-medium text-gray-900">
                    General Information
                  </h3>
                  <p className="mt-1 max-w-2xl text-sm leading-5 text-gray-500">
                    Personal details and links.
                  </p>
                </div>
                <div>
                  <dl>
                    <div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
                      <dt className="text-sm leading-5 font-medium text-gray-500">
                        Full name
                      </dt>
                      <dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
                        {`${user.first_name && user.first_name} ${
                          user.last_name && user.last_name
                        }`}
                      </dd>
                    </div>
                    <div className="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
                      <dt className="text-sm leading-5 font-medium text-gray-500">
                        Skillset
                      </dt>
                      <dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
                        <ul className="flex flex-wrap">
                          {user.tags.length &&
                            user.tags.map((tag, idx) => {
                              return (
                                <li key={idx} className="mr-3 my-1">
                                  <span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium leading-4 bg-blue-100 text-blue-800">
                                    {tag}
                                  </span>
                                </li>
                              )
                            })}
                        </ul>
                      </dd>
                    </div>
                    <div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
                      <dt className="text-sm leading-5 font-medium text-gray-500">
                        Email address
                      </dt>
                      <dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
                        {/* {`${user.email}`} */}
                      </dd>
                    </div>
                    <div className="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
                      <dt className="text-sm leading-5 font-medium text-gray-500">
                        Salary expectation
                      </dt>
                      <dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
                        {user.salary_indication ? salary.indication : ""}
                      </dd>
                    </div>
                    <div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
                      <dt className="text-sm leading-5 font-medium text-gray-500">
                        About
                      </dt>
                      <dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
                        {user.about ? user.about : ""}
                      </dd>
                    </div>
                  </dl>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </>
  )
}
Example #29
Source File: ListPage.jsx    From awesome-tools with MIT License 4 votes vote down vote up
export default function ListPage({
  tools,
  framework,
  title,
  showType = true,
  showCompatibleWith = true,
  showLicense = true,
}) {
  const router = useRouter();
  const query = router.query;
  const [ isFirstLoad, setLoad ] = useState(false);
  const [ exploreTools, setExploreTools ] = useState([]);
  const [ frameworks, setFrameworks ] = useState([]);
  const [ languages, setLanguages ] = useState([]);
  const [ licenses, setLicenses ] = useState([]);
  const [ renders, setRenders ] = useState([]);

  useEffect(() => {
    if (Object.keys(query).length && !isFirstLoad) {
      setParamsFromRouter(
        query,
        setExploreTools,
        setFrameworks,
        setLanguages,
        setLicenses,
        setRenders,
      );
      setLoad(true);
    }
  }, [ query ]);

  useEffect(() => {
    router.push(
      {
        scroll: false,
        query: {
          ...(framework && { framework }),
          tools: exploreTools,
          ...(!framework && { frameworks }),
          languages,
          licenses,
          renders
        },
      },
      undefined,
      { scroll: false },
    );
  }, [ framework, exploreTools, frameworks, languages, licenses, renders ]);

  const filteredTools = filter(
    tools,
    frameworks,
    languages,
    licenses,
    renders,
    exploreTools,
  );

  const setItem = (array, set, item) => {
    const index = array.indexOf(item);
    if (index === -1) {
      set([ ...array, item ]);
      // return true;
    } else {
      array.splice(index, 1);
      set([ ...array ]);
      // return false;
    }
  };

  return (
    <>
      <NextSeo
        title={`${title} — the awesome list`}
        description={`${title} for application developers: charting libraries, data grids, maps, etc.`}
      />

      <div className="container custom-container">
        <main>
          <H1>{title} <br className="xl-hidden" /> for application developers</H1>

          {showType && (
            <div className="row mb-md">
              {Object.values(allTypes).map(type => (
                <ExploreToolsCard
                  onClick={() => setItem(exploreTools, setExploreTools, type.slug)}
                  active={exploreTools.includes(type.slug) ? "active" : null}
                  text={type.name}
                  image={type.image}
                />
              ))}
            </div>
          )}

          {showCompatibleWith && (
            <div className="flex flex-wrap-row flex-items-center mb-sm">
              <AccentedText className="mr-xs">Compatible with</AccentedText>

              {Object.values(allFrameworks).map(framework => (
                <Chip
                  key={framework.slug}
                  className="mr-xs"
                  icon={framework.icon}
                  title={framework.name}
                  active={frameworks.includes(framework.slug) ? "active" : null}
                  onClick={() => setItem(frameworks, setFrameworks, framework.slug)}
                />
              ))}
            </div>
          )}

          <div className="flex flex-wrap-row flex-items-center mb-sm">
            <AccentedText className="mr-xs">With support for</AccentedText>

            <Chip
              icon="typescript.svg"
              title="TypeScript"
              active={languages.includes("typescript") ? "active" : null}
              onClick={() => setItem(languages, setLanguages, "typescript")} />
            {showLicense && (<AccentedText className="mr-xs ml-xs">and</AccentedText>)}
            {showLicense && (
              <>
                <Chip
                  className="mr-xs"
                  icon="open-source.svg"
                  title="open source"
                  active={licenses.includes("open-source") ? "active" : null}
                  onClick={() => setItem(licenses, setLicenses, "open-source")} />
                <Chip
                  icon="proprietary.svg"
                  title="proprietary"
                  active={licenses.includes("proprietary") ? "active" : null}
                  onClick={() => setItem(licenses, setLicenses, "proprietary")} />
                <AccentedText className="ml-xs">license</AccentedText>
              </>
            )}
          </div>
          <div className="flex flex-wrap-row flex-items-center">
            <AccentedText className="mr-xs">Rendering</AccentedText>

            <Chip
              title="Canvas"
              className="mr-xs"
              active={renders.includes("canvas") ? "active" : null}
              onClick={() => setItem(renders, setRenders, "canvas")} />
            <Chip
              title="SVG"
              className="mr-xs"
              active={renders.includes("svg") ? "active" : null}
              onClick={() => setItem(renders, setRenders, "svg")} />
            <Chip
              title="HTML"
              active={renders.includes("html") ? "active" : null}
              onClick={() => setItem(renders, setRenders, "html")} />
          </div>

          <div className="number-control-wrap">
            <ToolsNumberControl
              filteredTools={filteredTools}
              isChanged={
                exploreTools.length ||
                frameworks.length ||
                languages.length ||
                licenses.length ||
                renders.length
              }
              clearFilters={() => {
                clearFilters([
                  setExploreTools,
                  setFrameworks,
                  setLanguages,
                  setLicenses,
                  setRenders,
                ]);
              }}
            />
          </div>

          <div>
            <div className="row">
              {filteredTools &&
              filteredTools.map((tool) => (
                <div className="col-xl-6 mb-md" key={tool.id + Math.random()}>
                  {/* to lazy load on scroll need to set heigth */}
                  <ToolCard {...tool} />
                </div>
              ))}
            </div>
          </div>
        </main>
      </div>
    </>
  );
}