diff --git a/src/components/Card.js b/src/components/Card.js
index 1e44466..a677b77 100644
--- a/src/components/Card.js
+++ b/src/components/Card.js
@@ -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 (
+
+ )
+}
+
+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 (
+
+ )
+}
+
+export function Alternatives({ nameList, children }) {
+ const [show, setShow] = useState(false)
+
+ console.log(children)
+
+ function onClick() {
+ setShow(true)
+ }
+
+ return (
+ <>
+ {show ? (
+ nameList.map((name) => (
+
+ }>{children(name)}
+
+ ))
+ ) : (
+
+ Show Alternatives
+
+ )}
+ >
+ )
+}
+
+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;
diff --git a/src/components/GithubCard.js b/src/components/GithubCard.js
index 13a43b5..2794887 100644
--- a/src/components/GithubCard.js
+++ b/src/components/GithubCard.js
@@ -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 (
- }
- />
- )
-}
+import { Card, CardTitle, DedicatedAvailability, Alternatives } from './Card'
export default function GithubCard({ name }) {
return (
GitHub
-
+ }
+ />
+
+ {(name) => (
+ }
+ />
+ )}
+
)
}
diff --git a/src/components/HomebrewCard.js b/src/components/HomebrewCard.js
index ef6aa23..9601b05 100644
--- a/src/components/HomebrewCard.js
+++ b/src/components/HomebrewCard.js
@@ -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 (
- }
- />
- )
-}
-
export default function HomebrewCard({ name }) {
return (
Homebrew
-
+ }
+ />
)
}
diff --git a/src/components/JsOrgCard.js b/src/components/JsOrgCard.js
index c3d9aaf..bd06276 100644
--- a/src/components/JsOrgCard.js
+++ b/src/components/JsOrgCard.js
@@ -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 (
- }
- />
- )
-}
+import { Card, CardTitle, DedicatedAvailability } from './Card'
export default function JsOrgCard({ name }) {
return (
js.org
-
+ }
+ />
)
}
diff --git a/src/components/NpmCard.js b/src/components/NpmCard.js
index f448906..5a66d5a 100644
--- a/src/components/NpmCard.js
+++ b/src/components/NpmCard.js
@@ -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 (
- <>
- }
- />
- }
- url="https://www.npmjs.com/org/"
- prefix="npmjs.com/org/"
- />
- >
- )
-}
+import { Card, CardTitle, DedicatedAvailability } from './Card'
export default function NpmCard({ name }) {
return (
npm
-
+ }
+ />
+ }
+ />
)
}
diff --git a/src/components/TwitterCard.js b/src/components/TwitterCard.js
index cd7d2a7..e283ac6 100644
--- a/src/components/TwitterCard.js
+++ b/src/components/TwitterCard.js
@@ -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 (
- }
- />
- )
-}
+import { Card, CardTitle, DedicatedAvailability, Alternatives } from './Card'
+import { capitalize } from '../util/text'
export default function TwitterCard({ name }) {
return (
Twitter
-
+ }
+ />
+
+ {(name) => (
+ }
+ />
+ )}
+
)
}
diff --git a/src/services/npm-org.js b/src/services/npm-org.js
new file mode 100644
index 0000000..6a85958
--- /dev/null
+++ b/src/services/npm-org.js
@@ -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 })
+ }
+}
diff --git a/src/services/npm.js b/src/services/npm.js
index 9be607b..f50e6e6 100644
--- a/src/services/npm.js
+++ b/src/services/npm.js
@@ -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 })
}
diff --git a/src/util/text.js b/src/util/text.js
new file mode 100644
index 0000000..95f67a1
--- /dev/null
+++ b/src/util/text.js
@@ -0,0 +1,3 @@
+export function capitalize(text) {
+ return text[0].toUpperCase() + text.slice(1)
+}