1
0
mirror of https://github.com/uetchy/namae.git synced 2025-03-17 04:30:31 +09:00

chore: tidy up name list

This commit is contained in:
uetchy 2019-08-01 00:58:44 +09:00
parent 92529201e8
commit 19ffa22c29
4 changed files with 91 additions and 68 deletions

View File

@ -1,40 +1,62 @@
import React from 'react'
import React, { Suspense } from 'react'
import styled from 'styled-components'
import useFetch from 'fetch-suspense'
import { BarLoader } from 'react-spinners'
import { ExternalLink } from './Links'
function AvailabilityCell({
class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
this.state = { hasError: false }
}
static getDerivedStateFromError(error) {
return { hasError: true, message: error.message }
}
componentDidCatch(error, info) {}
render() {
if (this.state.hasError) {
return <h4>{this.state.message}</h4>
}
return this.props.children
}
}
const Result = ({
name,
availability,
link,
prefix = '',
suffix = '',
icon,
}) {
return (
<ItemContainer>
}) => (
<Container>
<Cell availability={availability}>
{icon}
<Item>
<Name>
<ExternalLink href={link}>
{prefix}
{availability ? (
<span style={{ color: 'green' }}>{name}</span>
) : (
<span style={{ color: 'red' }}>{name}</span>
)}
{name}
{suffix}
</ExternalLink>
</Item>
</ItemContainer>
)
}
</Name>
</Cell>
</Container>
)
export const Fallback = () => (
<ItemContainer>
const Fallback = () => (
<Container>
<BarLoader />
</ItemContainer>
</Container>
)
export const AvailabilityContainer = ({ children }) => (
<ErrorBoundary>
<Suspense fallback={<Fallback />}>{children}</Suspense>
</ErrorBoundary>
)
export function DedicatedAvailability({
@ -46,11 +68,13 @@ export function DedicatedAvailability({
icon,
}) {
const response = useFetch(`/availability/${service}/${name}`)
if (response.error) {
throw new Error(`${service}: ${response.error}`)
}
return (
<AvailabilityCell
<Result
availability={response.availability}
name={name}
link={link}
@ -70,12 +94,15 @@ export function ExistentialAvailability({
icon,
}) {
const response = useFetch(target, null, { metadata: true })
if (response.status !== 404 && response.status !== 200) {
throw new Error(`${name}: ${response.status}`)
}
const availability = response.status === 404
return (
<AvailabilityCell
<Result
name={name}
availability={availability}
link={link}
@ -86,16 +113,24 @@ export function ExistentialAvailability({
)
}
const ItemContainer = styled.div`
const Container = styled.div`
min-height: 1em;
display: flex;
align-items: center;
margin-top: 8px;
`
const Cell = styled.div`
display: flex;
flex-direction: row;
align-items: flex-start;
margin-top: 8px;
word-break: break-all;
color: ${({ availability }) => (availability ? 'green' : 'red')};
`
const Item = styled.span`
const Name = styled.span`
margin-left: 6px;
margin-top: -1px;
font-family: monospace;
font-size: 1rem;

View File

@ -1,32 +1,9 @@
import React, { Suspense, useState } from 'react'
import React, { useState } from 'react'
import styled from 'styled-components'
import { Fallback } from './Availability'
import { AvailabilityContainer } from './Availability'
import { mobile } from '../util/css'
class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
this.state = { hasError: false }
}
static getDerivedStateFromError(error) {
return { hasError: true, message: error.message }
}
componentDidCatch(error, info) {}
render() {
if (this.state.hasError) {
return <h4>{this.state.message}</h4>
}
return this.props.children
}
}
const BoundedSuspense = ({ children }) => (
<ErrorBoundary>
<Suspense fallback={<Fallback />}>{children}</Suspense>
</ErrorBoundary>
)
export function Card({ title, nameList, alternativeList = [], children }) {
const [revealAlternatives, setRevealAlternatives] = useState(false)
@ -37,33 +14,30 @@ export function Card({ title, nameList, alternativeList = [], children }) {
return (
<CardWrapper>
<CardTitle>{title}</CardTitle>
<>
<CardList>
{nameList.map((name) => (
<BoundedSuspense>{children(name)}</BoundedSuspense>
<AvailabilityContainer>{children(name)}</AvailabilityContainer>
))}
{revealAlternatives &&
alternativeList.map((name) => (
<BoundedSuspense>{children(name)}</BoundedSuspense>
<AvailabilityContainer>{children(name)}</AvailabilityContainer>
))}
</>
{alternativeList.length > 0 && !revealAlternatives ? (
<ShowAlternativesButton onClick={onClick}>
show alternatives
</ShowAlternativesButton>
) : null}
{alternativeList.length > 0 && !revealAlternatives ? (
<ShowAlternativesButton onClick={onClick}>
show more
</ShowAlternativesButton>
) : null}
</CardList>
</CardWrapper>
)
}
const CardWrapper = styled.div`
margin-bottom: 20px;
margin-bottom: 40px;
padding: 40px;
border-radius: 2px;
${mobile} {
padding: 20px;
box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1);
border-radius: 0;
padding: 0px;
}
`
@ -71,6 +45,20 @@ const CardTitle = styled.div`
font-size: 0.8rem;
font-weight: bold;
margin-bottom: 15px;
${mobile} {
padding-left: 20px;
}
`
const CardList = styled.div`
border-radius: 2px;
${mobile} {
padding: 20px;
box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1);
border-radius: 0;
}
`
const ShowAlternativesButton = styled.div`

View File

@ -10,11 +10,12 @@ export default function DomainCard({ name }) {
<Card
title="Domain"
key={lowerCase}
nameList={[`${lowerCase}.app`, `${lowerCase}.dev`, `${lowerCase}.org`]}
nameList={[`${lowerCase}.com`, `${lowerCase}app.com`, `${lowerCase}.app`]}
alternativeList={[
`${lowerCase}app.com`,
`get${lowerCase}.com`,
`${lowerCase}.dev`,
`${lowerCase}.io`,
`${lowerCase}.build`,
`get${lowerCase}.com`,
]}>
{(name) => (
<DedicatedAvailability

View File

@ -14,15 +14,14 @@ export default function NpmCard({ name }) {
name={name}
service="npm"
link={`https://www.npmjs.com/package/${name}`}
prefix="npmjs.com/"
icon={<FaNpm />}
/>
<DedicatedAvailability
name={name}
service="npm-org"
link={`https://www.npmjs.com/org/${name}`}
prefix="npmjs.com/~"
suffix=" (Org)"
prefix="@"
suffix=" (Organization)"
icon={<FaNpm />}
/>
</>