1
0
mirror of https://github.com/uetchy/namae.git synced 2025-03-16 20:20:38 +09:00

feat: alternatives

This commit is contained in:
uetchy 2019-07-31 01:12:51 +09:00
parent 7626959819
commit f9c70c3363
9 changed files with 185 additions and 124 deletions

View File

@ -1,5 +1,6 @@
import React, { Suspense } from 'react'
import React, { Suspense, useState } from 'react'
import styled from 'styled-components'
import useFetch from 'fetch-suspense'
import { BarLoader } from 'react-spinners'
export function Card({ children }) {
@ -49,6 +50,96 @@ export function AvailabilityCell({
)
}
export function DedicatedAvailability({
name,
provider,
url,
prefix = '',
suffix = '',
icon,
}) {
const response = useFetch(`/availability/${provider}/${name}`)
if (response.error) {
throw new Error(`${provider}: ${response.error}`)
}
return (
<AvailabilityCell
availability={response.availability}
name={name}
url={url}
prefix={prefix}
suffix={suffix}
icon={icon}
/>
)
}
export function ExistenceAvailability({
name,
target,
prefix = '',
suffix = '',
icon,
}) {
const response = useFetch(target, null, { metadata: true })
if (response.status !== 404 && response.status !== 200) {
throw new Error(`Homebrew: ${response.statusText}`)
}
const availability = response.status === 404
return (
<AvailabilityCell
name={name}
availability={availability}
url={`https://formulae.brew.sh/formula/${name}`}
prefix={prefix}
suffix={suffix}
icon={icon}
/>
)
}
export function Alternatives({ nameList, children }) {
const [show, setShow] = useState(false)
console.log(children)
function onClick() {
setShow(true)
}
return (
<>
{show ? (
nameList.map((name) => (
<ErrorBoundary>
<Suspense fallback={<BarLoader />}>{children(name)}</Suspense>
</ErrorBoundary>
))
) : (
<ShowAlternativesButton onClick={onClick}>
Show Alternatives
</ShowAlternativesButton>
)}
</>
)
}
const ShowAlternativesButton = styled.div`
display: inline-block;
margin-top: 10px;
padding: 5px 0;
border: none;
border-bottom: 1px dashed black;
cursor: pointer;
font-family: monospace;
font-size: 1rem;
`
class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
@ -77,7 +168,7 @@ const CardWrapper = styled.div`
border-radius: 2px;
`
const ItemContainer = styled.span`
const ItemContainer = styled.div`
display: flex;
flex-direction: row;
align-items: flex-start;

View File

@ -1,31 +1,30 @@
import React from 'react'
import useFetch from 'fetch-suspense'
import { Card, CardTitle, AvailabilityCell } from './Card'
import { FaGithub } from 'react-icons/fa'
function Availability({ name }) {
const response = useFetch(`/availability/github/${name}`)
if (response.error) {
throw new Error(`GitHub: ${response.error}`)
}
return (
<AvailabilityCell
name={name}
availability={response.availability}
url={`https://github.com/${name}`}
prefix="github.com/"
icon={<FaGithub />}
/>
)
}
import { Card, CardTitle, DedicatedAvailability, Alternatives } from './Card'
export default function GithubCard({ name }) {
return (
<Card key={name}>
<CardTitle>GitHub</CardTitle>
<Availability name={name} />
<DedicatedAvailability
name={name}
provider="github"
url={`https://github.com/${name}`}
prefix="github.com/"
icon={<FaGithub />}
/>
<Alternatives
nameList={[`${name.toLowerCase()}hq`, `${name.toLowerCase()}-team`]}>
{(name) => (
<DedicatedAvailability
name={name}
provider="github"
url={`https://github.com/${name}`}
prefix="github.com/"
icon={<FaGithub />}
/>
)}
</Alternatives>
</Card>
)
}

View File

@ -1,36 +1,17 @@
import React from 'react'
import useFetch from 'fetch-suspense'
import { Card, CardTitle, AvailabilityCell } from './Card'
import { Card, CardTitle, ExistenceAvailability } from './Card'
import { IoIosBeer } from 'react-icons/io'
function Availability({ name }) {
const response = useFetch(
`https://formulae.brew.sh/api/formula/${name}.json`,
null,
{ metadata: true }
)
if (response.status !== 404 && response.status !== 200) {
throw new Error(`Homebrew: ${response.statusText}`)
}
const availability = response.status === 404
return (
<AvailabilityCell
name={name}
availability={availability}
url={`https://formulae.brew.sh/formula/${name}`}
icon={<IoIosBeer />}
/>
)
}
export default function HomebrewCard({ name }) {
return (
<Card key={name}>
<CardTitle>Homebrew</CardTitle>
<Availability name={name} />
<ExistenceAvailability
name={name}
target={`https://formulae.brew.sh/api/formula/${name}.json`}
url={`https://formulae.brew.sh/formula/${name}`}
icon={<IoIosBeer />}
/>
</Card>
)
}

View File

@ -1,31 +1,18 @@
import React from 'react'
import useFetch from 'fetch-suspense'
import { Card, CardTitle, AvailabilityCell } from './Card'
import { FaJsSquare } from 'react-icons/fa'
function Availability({ name }) {
const response = useFetch(`/availability/jsorg/${name}`)
if (response.error) {
throw new Error(`Twitter: ${response.error}`)
}
return (
<AvailabilityCell
name={name}
availability={response.availability}
url={`https://${name}.js.org`}
suffix=".js.org"
icon={<FaJsSquare />}
/>
)
}
import { Card, CardTitle, DedicatedAvailability } from './Card'
export default function JsOrgCard({ name }) {
return (
<Card key={name}>
<CardTitle>js.org</CardTitle>
<Availability name={name} />
<DedicatedAvailability
name={name}
provider="jsorg"
url={`https://${name}.js.org`}
suffix=".js.org"
icon={<FaJsSquare />}
/>
</Card>
)
}

View File

@ -1,40 +1,25 @@
import React from 'react'
import useFetch from 'fetch-suspense'
import { Card, CardTitle, AvailabilityCell } from './Card'
import { FaNpm } from 'react-icons/fa'
function Availability({ name }) {
const response = useFetch(`/availability/npm/${name}`)
if (response.error) {
throw new Error(`npm: ${response.error}`)
}
return (
<>
<AvailabilityCell
name={name}
availability={response.packageAvailability}
url={`https://www.npmjs.com/package/${name}`}
prefix="npmjs.com/package/"
icon={<FaNpm />}
/>
<AvailabilityCell
name={name}
availability={response.orgAvailability}
icon={<FaNpm />}
url="https://www.npmjs.com/org/"
prefix="npmjs.com/org/"
/>
</>
)
}
import { Card, CardTitle, DedicatedAvailability } from './Card'
export default function NpmCard({ name }) {
return (
<Card key={name}>
<CardTitle>npm</CardTitle>
<Availability name={name.toLowerCase()} />
<DedicatedAvailability
name={name}
provider="npm"
url={`https://www.npmjs.com/package/${name}`}
prefix="npmjs.com/package/"
icon={<FaNpm />}
/>
<DedicatedAvailability
name={name}
provider="npm-org"
url={`https://www.npmjs.com/org/${name}`}
prefix="npmjs.com/org/"
icon={<FaNpm />}
/>
</Card>
)
}

View File

@ -1,31 +1,31 @@
import React from 'react'
import useFetch from 'fetch-suspense'
import { Card, CardTitle, AvailabilityCell } from './Card'
import { FaTwitter } from 'react-icons/fa'
function Availability({ name }) {
const response = useFetch(`/availability/twitter/${name}`)
if (response.error) {
throw new Error(`Twitter: ${response.error}`)
}
return (
<AvailabilityCell
name={name}
availability={response.availability}
url={`https://twitter.com/${name}`}
prefix="twitter.com/"
icon={<FaTwitter />}
/>
)
}
import { Card, CardTitle, DedicatedAvailability, Alternatives } from './Card'
import { capitalize } from '../util/text'
export default function TwitterCard({ name }) {
return (
<Card key={name}>
<CardTitle>Twitter</CardTitle>
<Availability name={name} />
<DedicatedAvailability
name={name}
provider="twitter"
url={`https://twitter.com/${name}`}
prefix="twitter.com/"
icon={<FaTwitter />}
/>
<Alternatives
nameList={[`${capitalize(name)}HQ`, `${name.toLowerCase()}app`]}>
{(name) => (
<DedicatedAvailability
name={name}
provider="twitter"
url={`https://twitter.com/${name}`}
prefix="twitter.com/"
icon={<FaTwitter />}
/>
)}
</Alternatives>
</Card>
)
}

16
src/services/npm-org.js Normal file
View File

@ -0,0 +1,16 @@
const npmName = require('npm-name')
module.exports = async (req, res) => {
const name = req.query.name
if (!name) {
return res.status(400).json({ error: 'no query given' })
}
try {
const availability = await npmName(`@${name}`)
res.json({ availability })
} catch (err) {
res.status(400).json({ error: err.message })
}
}

View File

@ -8,9 +8,8 @@ module.exports = async (req, res) => {
}
try {
const packageAvailability = await npmName(name)
const orgAvailability = await npmName(`@${name}`)
res.json({ packageAvailability, orgAvailability })
const availability = await npmName(name)
res.json({ availability })
} catch (err) {
res.status(400).json({ error: err.message })
}

3
src/util/text.js Normal file
View File

@ -0,0 +1,3 @@
export function capitalize(text) {
return text[0].toUpperCase() + text.slice(1)
}