import React, { useEffect, useState } from 'react'; import classNames from 'classnames'; import { fetchGet, ResponseError } from '../fetch'; enum MetadataLoadState { Inactive, Loading, Success, Failed, } type Metadata = { url: string; title: string; description: string; image: string; expires_at: string | null; tags: { name: string; }[]; }; type Suggestion = { name: string; used: boolean; }; type MetadataPreviewProps = { link: string; tags: string[]; onClickTag: (tag: string) => void; }; const MetadataLoading = () => (
オカズの情報を読み込んでいます…
); const MetadataLoadFailed = () => (
オカズの情報を読み込めませんでした
); export const MetadataPreview: React.FC = ({ link, tags, onClickTag }) => { const [state, setState] = useState(MetadataLoadState.Inactive); const [metadata, setMetadata] = useState(null); useEffect(() => { if (link.trim() === '' || !/^https?:\/\//.test(link)) { setState(MetadataLoadState.Inactive); setMetadata(null); return; } setState(MetadataLoadState.Loading); fetchGet('/api/checkin/card', { url: link }) .then((response) => { if (!response.ok) { throw new ResponseError(response); } return response.json(); }) .then((data) => { setState(MetadataLoadState.Success); setMetadata(data); }) .catch(() => { setState(MetadataLoadState.Failed); setMetadata(null); }); }, [link]); if (state === MetadataLoadState.Inactive) { return null; } const hasImage = metadata !== null && metadata.image !== ''; const descClasses = classNames({ 'col-8': hasImage, 'col-12': !hasImage, }); const tagClasses = (s: Suggestion) => classNames({ 'list-inline-item': true, badge: true, 'badge-primary': !s.used, 'badge-secondary': s.used, 'metadata-tag-item': true, }); const suggestions = metadata?.tags.map((t) => ({ name: t.name, used: tags.indexOf(t.name) !== -1, })) ?? []; return (
{state === MetadataLoadState.Loading ? ( ) : state === MetadataLoadState.Success ? (
{hasImage && (
Thumbnail
)}
{metadata?.title}
{suggestions.length > 0 && ( <>

タグ候補
(クリックするとタグ入力欄にコピーできます)

    {suggestions.map((tag) => (
  • onClickTag(tag.name)} > {tag.name}
  • ))}
)}
) : ( )}
); };